最近需要用到Django的MySQL读写分离技术,查了一些资料,把方法整理了下来。

在Django里实现对MySQL的读写分离,实际上就是将不同的读写请求按一定的规则路由到不同的数据库上(可以是不同类型的数据库),我们需要做的就是,定义不同的数据库,定义不同的路由规则。当然前提是你需要手动实现MySQL的主从同步..

首先定义我们的主从数据库:

DATABASES = {    'default': {        'ENGINE': 'django.db.backends.mysql',        'NAME': 'ospf',        'USER': 'root',        'PASSWORD': 'hunantv',    },    'slave': {        'ENGINE': 'django.db.backends.mysql',        'NAME': 'ospf',        'USER': 'ospf',        'PASSWORD': 'hunantv',        'HOST': '192.168.8.52'    }}

定义我们的路由规则,路由规则可以有好多个,每个规则是一个类。如下所示:  

import socketfrom django.conf import settingsdef test_connection_to_db(database_name):    try:        db_definition = getattr(settings, 'DATABASES')[database_name]        s = socket.create_connection((db_definition['HOST'], 3306), 2)        s.close()        return True    except (AttributeError, socket.timeout) as e:        return Falseclass FailoverRouter(object):    def db_for_read(self, model, **hints):        if model._meta.app_label == 'ospf' and test_connection_to_db('slave'):            return 'slave'        return 'default'    def db_for_write(self, model, **hints):        "Point all writes to the default db"        return 'default'    def allow_relation(self, obj1, obj2, **hints):        db_list = ('default', 'slave')        if obj1._state.db in db_list and obj2._state.db in db_list:            return True        return None    def allow_syncdb(self, db, model):        "Make sure only the default db allows syncdb"        return db == 'default'

db_for_read.有个read故名思议就是从哪里读. app_label是应用的名称.. 

由于我希望用户、权限表还是从主数据库读,,所以就加了这个限制.. test_connection_to_db 是判断从数据库是否异常,, 在异常的情况下会自动到 主数据库读取.. 

最后在setting.py中加上这个路由规则:

DATABASE_ROUTERS = ['lvs.models.FailoverRouter']

因为Django不负责主从数据库之间的同步,所以如果在读取完数据后马上要对数据进行操作,可以显式地使用主数据库来读取并修改数据。

>>> Author.objects.using('default').all() 

>>> my_object.save(using='default')