1. 程式人生 > 其它 >【Django雜記】django的讀寫分離

【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='[email protected]')
  • 分庫分表
    • 在大型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',]