源码分析peewee orm的读写分离

就不再长篇大论了…   我相信很多朋友都在使用ORM库来代替繁杂的原生的sql语句。 但如果有特需一点的需求,比如要主从分离?  我们以前的做法很是暴力,直接修改peewee的源码,当他在调用select相关函数的时候,会重置一个mysql db连接,当然是改成从库。   近期才发现peewee的BaseModel有read_slaves参数….


该文章写的有些乱,欢迎来喷 ! 另外文章后续不断更新中,请到原文地址查看更新.

http://xiaorui.cc/?p=3729

除了上面乱改代码之外,还有这些….. 因为业务有大量的分库分表存在,这样导致一个现象,我们要输出N个表对象,我不能忍这个,所以改代码。 我们是在python peewee里加了一个patch组件,绕过了几个逻辑。 原理倒是简单,其实主要难度在于读懂peewee的源码。 当每次初始化程序的时候会从redis获取最新的分库分表配置信息,大多是通过id和时间区间来分表。 这peewee的改造工程是不小的, 找个时间专门给大家讲述一下。按我的经验来说,每个语言的web框架都是该语言的精华,里面有各种的语法糖,黑魔法的使用 。

言归正传 我们还是继续聊peewee的读写分离。   直接看源码…   这个是peewee实现主从读写分离的主要功能类,原理就是继承modol,重写了select和raw函数…. 另外通过_get_read_database来RR轮训的方式来获取从mysql连接对象。 

#xiaorui.cc
class ReadSlaveModel(Model):
    @classmethod
    def _get_read_database(cls):
        if not getattr(cls._meta, 'read_slaves', None):
            return cls._meta.database
        current_idx = getattr(cls, '_read_slave_idx', -1)
        cls._read_slave_idx = (current_idx + 1) % len(cls._meta.read_slaves)
        return cls._meta.read_slaves[cls._read_slave_idx]

    @classmethod
    def select(cls, *args, **kwargs):
        query = super(ReadSlaveModel, cls).select(*args, **kwargs)
        query.database = cls._get_read_database()
        return query

    @classmethod
    def raw(cls, *args, **kwargs):
        query = super(ReadSlaveModel, cls).raw(*args, **kwargs)
        if query._sql.lower().startswith('select'):
            query.database = cls._get_read_database()
        return query

这个peewee的主从使用方法很简单,毕竟都封装差不多了,对于你我来说,只管用就可以了。  也就我是我闲着没事总想看看人家源码是怎么实现的,O(∩_∩)O~….

from config import MYSQL_CONF

master = MySQLDatabase('buzz_master', **MYSQL_CONF)
read_db = MySQLDatabase('buzz_master', **MYSQL_CONF)
read_db2 = MySQLDatabase('buzz_master', **MYSQL_CONF)

from playhouse.pool import PooledMySQLDatabase

db = PooledMySQLDatabase(
    database='buzz_master',
    max_connections=16,
    stale_timeout=600,**MYSQL_CONF)

class BaseModel(Model):
    class Meta:
        database = master
        read_slaves = [read_db,read_db2]

这样就完事了…   peewee的select都会从 从mysql 取数据。 如果你有一些原因导致你要从master取数据,那么可以使用SelectQuery方法。 

现在mysql分库分表的读写逻辑,大多数公司都是放在proxy层面来实现的,因为能更好的统一入库,对于大多数程序来说,他只关心纯业务就可以了。  但也有些公司例外,比如唯品会, 蘑菇街,他们是在本程序里面实现的分库分表。   作为程序员我更喜欢第一种,因为我省事了。  

但我也知道当前开源的mysql代理没几个太靠谱的,像mycat,功能很丰富,但性能不咋地….  像mysql proxy ,性能和功能都是个渣,   像陈非的kingshard,我暂时还不敢用,虽然我曾经给kingshard捐过钱….      


大家觉得文章对你有些作用! 如果想赏钱,可以用微信扫描下面的二维码,感谢!
另外再次标注博客原地址  xiaorui.cc

1 Response

  1. 卓修武 2016年8月26日 / 下午9:25

    peewee 跟 django 的orm框架部分 是不是差不多

发表评论

邮箱地址不会被公开。 必填项已用*标注