django 实现读写分离

  • 主要目的:单个数据库进行读写操作频繁,降低速度,增加服务器读写数据库压力,为了解决这一问题,对数据库进行读写分离,将大大提升项目的性能。其基本原理是:
    • 让主数据库处理事务性的增删改查,而从数据库处理查询操作,当主数据库因一些事务性操作导致数据变更后,同步更新到其他读库。写库一个,读库可以有多个。采用日志同步的方式实现主从同步。
  1. 在Django的配置文件settings.py中,DATABASES中添加代码如下:

    DATABASES = {
        'default': {
            'ENGINE': 'django.db.backends.mysql',
            'HOST': '127.0.0.1',  # 主服务器的运行ip
            'PORT': 3306,   # 主服务器的运行port
            'USER': 'django',  # 主服务器的用户名
            'PASSWORD': 'django',  # 主服务器的密码
            'NAME': 'djangobase'   #  数据表名
        },
        'slave': {
            'ENGINE': 'django.db.backends.mysql', 
            'HOST': '127.0.0.1',
            'PORT': 8306,
            'USER': 'django_slave',
            'PASSWORD': 'django_slave',
            'NAME': 'djangobase_slave'
        }
    }  
    
  2. 在models.py创建完表后,进行数据库迁移

    python manage.py makemigrations  # 在migrations文件夹下生成记录
    python manage.py migrate --database default  # 默认可以不写参数
    python manage.py migrate --database slave  # 在从库再迁移一次,就可以在上面建立相同的表
    
  3. 创建数据库操作的路由分类

    • 使用sqllite

  • 使用mysql

  • 在项目的utils中创建db_router.py文件,并在该文件中定义一个db类,用来进行读写分离
#读写分离
class MasterSlaveDBRouter(object):
 
    def db_for_read(self, model, **hints):
        """读数据库"""
        return "slave"
 
    def db_for_write(self, model, **hints):
        """写数据库"""
        return "default"    #默认的库 读
 
    def allow_relation(self, obj1, obj2, **hints):
        """是否运行关联操作"""
        return True  

#一主多从  多个数据库读  一个数据库写
class Router:

    def db_for_write(self, model, **kwargs):
        return 'db1'

    def db_for_read(self, model, **kwargs):
        return random.choices['db2', 'db3', 'db4']
    
#分库分表
class Router:

    def db_for_write(self, model, **kwargs):
        app_name = model._meta.app_label
        if app_name == 'app01':
            return 'db1'
        elif app_name == 'app02':
            return 'db2'

    def db_for_read(self, model, **kwargs):
        app_name = model._meta.app_label
        if app_name == 'app01':
            return 'db1'
        elif app_name == 'app02':
            return 'db2'
  1. 配置读写分离路由

    • 在配置文件中增加
    #配置读写分离
    DATABASE_ROUTERS = ['项目名.utils.db_router.MasterSlaveDBRouter("自定义的类名称")']
    
  2. 还可以使用手动的方式进行读写分离

    • 进行orm操作的时候使用using操作对应数据库
    def write(request):
        models.User.objects.using('default').create(name='张三', pwd='123', phone=1234)
        return HttpResponse('写成功')
    
    
    def read(request):
        obj = models.User.objects.filter(id=1).using('db2').first()
        return HttpResponse('读成功')
    

posted on 2021-02-23 18:04  Plyc  阅读(138)  评论(0编辑  收藏  举报

导航