【Django杂记】django的读写分离

1、一主一从
  • 数据库配置setting.py
DATABASES = {
    'default': {
        'ENGINE': 'django.db.backends.mysql',
        'NAME': 'db_hydra1',
        'HOST': '192.168.50.51',
        'PORT': 3306,
        'USER': 'root',
        'PASSWORD': '123456'
    },
    'db1': {
        'ENGINE': 'django.db.backends.mysql',
        'NAME': 'db_hydra1',
        'HOST': '192.168.50.52',
        'PORT': 3306,
        'USER': 'root',
        'PASSWORD': '123456'
    }
}
  • 数据迁移
# 如果正常执行,就会迁移到default中
python manage.py makemigrations

# 可以指定需要迁移的app和指定的数据库
python manage.py migrate [app名称] --database=[配置文件数据库名称的别名]
  • 手动操作views.py中
    • 写操作:指定使用db1
models.Userinfo.objects.using('db1').create(name='mark', age=18, gender='women')
    • 读操作:指定使用db1
res = models.Userinfo.objects.all().using('db1')
  • 自动操作:
    • 通过配置数据库路由,来自动实现,这样就不需要每次读写都手动指定数据库了。数据库路由中提供了四个方法(db_for_read、db_for_write、allow_relation、allow_migrate)
      • db_for_read(model, **hints):决定读操作的数据库
      • db_for_write(model, **hints):决定写操作的数据库
      • allow_relation(obj1, obj2, **hints)
        • 如果obj1和obj2之间应该允许关联则返回True,如果应该防止关联则返回False,如果路由无法判断则返回None。这是纯粹的验证操作,外键和多对多操作使用它来决定两个对象之间是否应该允许一个关联。
      • allow_migrate(db, app_label,model_name=None, **hints)    
        • 定义迁移操作是否允许在别名为db的数据库上运行。如果操作应该运行则返回True,如果不应该运行则返回False,如果路由无法判断则返回None。
        • app_label:是正在迁移的应用的标签。
    • 在app下创建router.py
class Router1:
    # 读操作使用:db1
    def db_for_read(self, model, **hints):
        return 'db1'
    # 写操作使用:default
    def db_for_write(self, model, **hints):
        return 'default'
    • 在settings.py中添加
DATABASE_ROUTERS = ['router.Router1',]
    • 读写都正常使用
# 写操作
models.Userinfo.objects.create(name='wot', age=18, gender='male')

# 读操作
res = models.Userinfo.objects.all()
2、一主一从(更细力度)
  • 在app下创建router.py
class Router1:
    # 读操作:如果表是userinfo就用db1,否则就使用default
    def db_for_read(self, model, **hints):
        if model._meta.model_name == 'user':
            return 'db1'
        else:
            return 'default'
    # 写操作使用:default
    def db_for_write(self, model, **hints):
        return 'default'
3、分库分表
    • app01中的表在default数据库创建
    • app02中的表在db1数据库创建
    • 生成迁移文件
python manage.py makemigraions 
    • app01中的表在default数据库创建
python manage.py migrate app01 --database=default
    • app02中的表在db1数据库创建
python manage.py migrate app02 --database=db1
  • 手动操作
# app01的写操作
models.Book.objects.using('default').create(title='金庸')

# app02的写操作
mmodels.Userinfo.objects.using('db1').create(name='mary',email='11111@qq.com')
  • 分库分表
    • 在大型web项目中,常常会创建多个app来处理不同的业务,如果希望实现app之间的数据库分离,比如app01走数据库db1,app02走数据库default
    • router.py
class Router1:
    def db_for_read(self, model, **hints):
        if model._meta.app_label == 'app01':
            return 'db1'
        if model._meta.app_label == 'app02':
            return 'default'

        def db_for_write(self, model, **hints):
            if model._meta.app_label == 'app01':
                return 'db1'
             if model._meta.app_label == 'app02':
            return 'default'
  • settings.py
DATABASE_ROUTERS = ['router.Router1',]
  • 读写操作
# 写操作
models.Userinfo.objects.create(name='wot', age=18, gender='male')

# 读操作
res = models.Userinfo.objects.all()
  • 数据库迁移时进行约束
class Router1:
    def allow_migrate(self, db, app_label, model_name=None, **hints):
        if db=='db1' and app_label == 'app02':
            return True
        elif db == 'default' and app_label == 'app01':
            return True
        else:
            return False

        # 如果返回None,那么表示交给后续的router,如果后续没有router,则相当于返回True

        def db_for_read(self, model, **hints):
            if model._meta.app_label == 'app01':
                return 'default'
            else:
                return 'db1'

            def db_for_write(self, model, **hints):
                if model._meta.app_label == 'app01':
                    return 'default'
                else:
                    return 'db1'
4、一主多从
  • 读写分离
    • 写操作全部使用主库的default
    • 读操作随机使用3个从库
  • 在app下创建router.py
class Router1:
    def db_for_read(self, model, **hints):
        db_list = ['db1', 'db2', 'db3']
        return random.choice(db_list)

    def db_for_write(self, model, **hints):
        return 'default'
  • setting.py
DATABASES = {
    'default': {
        'ENGINE': 'django.db.backends.mysql',
        'NAME': 'selfManage',
        'HOST': '127.0.0.1',
        'PORT': 3306,
        'USER': 'root',
        'PASSWORD': 'root'
    },
    'db1': {
        'ENGINE': 'django.db.backends.mysql',
        'NAME': 'selfManage',
        'HOST': '127.0.0.2,
        'PORT': 3306,
        'USER': 'root',
        'PASSWORD': 'root'
    },
    'db2': {
        'ENGINE': 'django.db.backends.mysql',
        'NAME': 'selfManage',
        'HOST': '127.0.0.3',
        'PORT': 3306,
        'USER': 'root',
        'PASSWORD': 'root'
    },
    'db3': {
        'ENGINE': 'django.db.backends.mysql',
        'NAME': 'selfManage',
        'HOST': '127.0.0.4',
        'PORT': 3306,
        'USER': 'root',
        'PASSWORD': 'root'
    }
}
  • settings.py
DATABASE_ROUTERS = ['router.Router1',]
posted @ 2022-05-31 13:39  郭祺迦  阅读(103)  评论(0)    收藏  举报