Pkold

cache kv python sqlite

python基于sqlite线程安全/进程安全的缓存-有趣儿的脑洞

基于内存中sqlite的缓存系统

Python disk backed cache

说是基于磁盘 实际上再linux上新建一个内存盘 把sqlite文件设置到内存盘中就可以了

安装
pip install diskcache
使用
import diskcache

#设置文件到内存中。=。  速度还不错
cache = diskcache.Cache("/tmp")


#写入缓存
cache.set(
    key="key"
    value="内容",
    expire="过期时间",
    tag="命名空间”
)


#手动清除超过生存时间的缓存
cache.cull()

#清除命名空间的缓存
cache.evict()

号称 Thread-safe and process-safe 经过测试还不错!

blog

关于本博客

blog

技能点

  • linux

日常生活和开发环境使用 自使用至今已有五六年

  • php

启蒙语言之一 刚接触建站的时候帮我进入了编程的世界

  • python

周末语言之一 日常在npm和pypi淘宝 本站点也是基于py3开发 02180712更新 真的爽!!!

  • nodejs

周末语言之一 乐趣!

  • java

工作语言 现就职于开源中国的java工程师

联系我

admin@pkold.com

https://github.com/zhenruyan/

关于本站

开发结构

nginx(tengine) 反向代理

nodejs + pm2
 + python3  + 
  uvloop(更新python3.7后 asyncio速度已经不差与uvloop 故删除此部分) 
   +  tornado +  fastcache(后期更换为了diskcache)  
   +  mongodb(后期更换成为postgresql)
     + markdown

网站第一版就是每天早上起床后写1个小时大约两周的产物

前端极为简单  懒

rps  大约能跑到500

个人感受

python 的面向对象用起来比java的要舒服一些

尴尬的程度处于  js  和  java  之间

(默哀胎死腹中的nodejs版本和php版本)

pm2 是个好东西

博客程序迭代完善后开源

开发版本

  • 20181228 博客数据库更换成pg,进行seo优化

  • 20181123 博客运行良好,准备加一个大佬名言。从日更变周更,最后变月更,友链功能遥遥无期

  • 20180813 修复内存泄漏- - 搜索依旧不优雅 ,访问记录依旧丑陋 等稍微的修修准备把这丑代码丢出去- - (竟然真的有人不知道tornado如何下手,那我的博客多少还是有了一点价值)

  • 20180801 博客的线程模型进行了重构,数据访问层一个线程池,日志一个线程池。 下一个版本完善多进程模型

  • 20180707 博客视图层进行了重构,进行了猜想式的重构,以多线程异步的方式构建视图

  • 20180626 博客终于有了搜索

  • 20180625 加入了whoosh作搜索,但是性能低下,暂时不放在前端

  • 20180605 修复cpu长期占用100%的问题 rps再次500+

  • 20180530 完善了seo优化,前端稍微做了改动

  • 20180501 第一个简单的版本 增删改查

  • 20180524 第二个版本 完善成一个基本完成的博客

arangodb nosql

arangodb 的配置优化

线上运行arangodb要做的优化! 前提当然一定是linux

启动参数

cpu分配内存块
numactl --interleave=all 


systemd 编写services时  需要写绝对路径
ExecStart=/usr/bin/numactl --interleave=all
内存回收机制
sudo bash -c "echo madvise >/sys/kernel/mm/transparent_hugepage/enabled"
sudo bash -c "echo madvise >/sys/kernel/mm/transparent_hugepage/defrag"
内存分配
sudo bash -c "echo 2 > /proc/sys/vm/overcommit_memory"
zone_reclaim_mode(据说是缓存)
sudo bash -c "echo 0 >/proc/sys/vm/zone_reclaim_mode"
多线程最大内存?
数值=cpu核心数 x 8 x 1000
sudo bash -c "sysctl -w 'vm.max_map_count=320000'"
禁用内存池
export GLIBCXX_FORCE_NEW=1
虚拟内存
/proc/sys/vm/overcommit_ratio (100 * (max(0, (RAM - Swap Space)) / RAM)) 

sudo bash -c "echo 97 > /proc/sys/vm/overcommit_ratio"
city ip log tornado

tornado 异步日志统计获取IP地址和对应城市

异步日志统计获取IP地址和对应城市

ip转城市

直接贴代码

class Singleton(type):
    _instances = {}

    def __call__(cls, *args, **kwargs):
        if cls not in cls._instances:
            cls._instances[cls] = super(Singleton, cls).__call__(*args, **kwargs)
        return cls._instances[cls]


class SearchIp(metaclass=Singleton):
    def __init__(self):
        try:
            dbpath = os.path.abspath("./utils/ip/ip2region.db")
            self.search = Ip2Region(dbpath)
        except IOError:
            log.error("err connect db",IOError.errno)
        else:
            log.info("db connect success")

    def getSession(self):
        return self.search
    def searchCity(self,ip):
        try:
            if self.getSession().isip(ip):
                city =  self.getSession().btreeSearch(ip=ip).get("region","火星").decode("utf-8")
            else:
                city = "火星"
        except IOError:
            log.error(IOError)
            city = "火星"
            return city
        else:
            return city
    def close(self):
        self.search.close()

单例模式 然后ip转城市

异步存到mongodb

class baseHttp (tornado.web.RequestHandler):
    executor = ThreadPoolExecutor(100)

        @tornado.web.asynchronous
        @tornado.gen.coroutine
        def initialize(self):
            yield self.logsave()

        @run_on_executor
        def logsave(self):
            ipDao.saveLog(self.request.remote_ip,self.request.uri,self.request.headers.get("User-Agent","鬼知道"))

似乎还凑活~~

python threadpoolexecutor tornado

python tornado ThreadPoolExecutor实现异步

tornado

#!/bin/env python
# -*- coding:utf-8 -*-
## 异步demo
import tornado.httpserver
import tornado.ioloop
import tornado.options
import tornado.web
from tornado import httpclient
import tornado.gen
from tornado import gen
from tornado.concurrent import run_on_executor
from concurrent.futures import ThreadPoolExecutor
import time
from tornado.options import define, options
define("port", default=8000, help="run on the given port", type=int)
class SleepHandler(tornado.web.RequestHandler):
    executor = ThreadPoolExecutor(10000)
    @tornado.web.asynchronous
    @tornado.gen.coroutine
    def get(self):
        # 假如你执行的异步会返回值被继续调用可以这样(只是为了演示),否则直接yield就行
        res = yield self.sleep()
        self.write("when i sleep %s s" % res)
        self.finish()
    @run_on_executor
    def sleep(self):
        for a in  range(1,900000):
            print(a)
        return 5
class JustNowHandler(tornado.web.RequestHandler):
    def get(self):
        self.write("i hope just now see you")
if __name__ == "__main__":
    tornado.options.parse_command_line()
    app = tornado.web.Application(handlers=[
            (r"/sleep", SleepHandler), (r"/justnow", JustNowHandler)])
    http_server = tornado.httpserver.HTTPServer(app)
    http_server.listen(options.port)
    tornado.ioloop.IOLoop.instance().start()
linux python queue zbus

记录一次zbus在Python上推送报Exception in thread Thread-2异常

记录一次zbus在Python上推送报Exception in thread Thread-2异常的解决办法,实际上是python的包管理确实坑了我

昨天还好好的 今天zbus 推送的时候一直报Exception in thread Thread-2

用git 回退到昨天

依旧报

神奇的。。。

修改zbus存放index目录

无效

重新创建一个venv环境

= = 成功

重新的去检查pip freeze

挑出我用的包

重新干掉venv 生成

安装

== 解决了 抓狂、、、

经过考虑应该是卸载不干净依赖的包的锅

= = 继续填坑

java linux mq python rpc zbus 队列

python使用zbus队列尝试

zbus小巧而极速的MQ, RPC实现, 支持HTTP/TCP代理,开放易扩展,多语言支撑微服务,系统总线架构

小巧而极速的MQ, RPC实现, 支持HTTP/TCP代理,开放易扩展,多语言支撑微服务,系统总线架构

最近再想做对外api服务,再纠结数据库异步驱动后

突然想起了zbus = =

这似乎是一个代价更小的方案

先试试官方demo

发布者

broker = Broker('localhost:15555') 

p = Producer(broker) 
p.declare('MyTopic') 

msg = Message()
msg.topic = 'MyTopic'
msg.body = 'hello world'

res = p.publish(msg)

消费者

broker = Broker('localhost:15555')  

def message_handler(msg, client):
    print(msg)

c = Consumer(broker, 'MyTopic')
c.message_handler = message_handler 
c.start()

消费者会一直阻塞 只要有资源 就会取到 然后调用回调

经过测试 body可以随意写 都可以序列化

那么数据入库的结构就可以这样

tornado -> httpapi -> 队列塞进去

队列 <---> 消费者 --> 数据库

cpu100% 博客 性能

记录一次博客性能修复

博客突然cpu100,还好不是玄学调优

博客建立之初 rps 可以跑到 500

cpu 几乎再百分之2左右

某天突然发现一直维持再100%

测试数据库 没有效果

数据库索引 没有效果

缓存命中 没有效果

从单进程到多进程 没有效果

好吧 怀疑人生

冥思苦想很久

突然想起老大说过markdown解析非常耗费时间

给markdown 加一个缓存

rps 瞬间到500+

完美!

mongodb 多表

mongoengine 多表查询写入

mongoengine 实现多表查询写入,动态查询存储

def ArticleDoyColl(coll="free"):
    class ArticleSave(mongo.Document):
        meta = {
            "collection":coll'indexes':[

                'name',

            ],          
            }
        name = mongo.StringField()
    return ArticleSave

if __name__ == "__main__":
    a = ArticleDoyColl("free")
    b=a.objects()
    print(b)

这个可以通过在meta字典里声明一个叫键为 'collection', 定义索引 indexes

deepin linux 深度系统 蓝牙 键盘