Django におけるリードレプリカ(読み取り専用DB)の導入は、データベースルーター(Database Router) を使って 読み取りと書き込みを自動で振り分ける方法 が王道です。
この記事では読み取りと書き込みを自動で振り分ける方法を紹介します。
前提は以下の通り。
- Django4.2
- AWS RDS writer とreader データベースを作成済み
目次
settings.py で複数DBを定義
default
が 書き込み用(Writer)replica
が 読み取り用(リードレプリカ)
DATABASES = {
'default': {
'ENGINE': 'django.db.backends.mysql',
'NAME': 'your_db_name',
'USER': 'your_user',
'PASSWORD': 'your_password',
'HOST': 'writer-db.cluster-xxxxxxxx.ap-northeast-1.rds.amazonaws.com',
'PORT': '3306',
},
'replica': {
'ENGINE': 'django.db.backends.mysql',
'NAME': 'your_db_name',
'USER': 'your_user',
'PASSWORD': 'your_password',
'HOST': 'reader-db.cluster-ro-xxxxxxxx.ap-northeast-1.rds.amazonaws.com',
'PORT': '3306',
}
}
データベースルーターの実装
from django.conf import settings
class MasterSlaveRouter:
def db_for_read(self, model, **hints):
# 読み取り系は replica にルーティング
return 'replica'
def db_for_write(self, model, **hints):
# 書き込みは常に default
return 'default'
def allow_relation(self, obj1, obj2, **hints):
# 関係のあるオブジェクト間であれば許可
db_list = settings.DATABASES.keys()
if obj1._state.db in db_list and obj2._state.db in db_list:
return True
return None
def allow_migrate(self, db, app_label, model_name=None, **hints):
# マイグレーションは default のみ
return db == 'default'
複数リードレプリカのランダム振り分け
必要であれば、複数のリードレプリカをランダムで振り分けることもできます。
from django.conf import settings
import random
class MasterSlaveRouter:
REPLICAS = ['replica1', 'replica2', 'replica3']
def db_for_read(self, model, **hints):
return random.choice(REPLICAS)
def db_for_write(self, model, **hints):
# 書き込みは常に default
return 'default'
def allow_relation(self, obj1, obj2, **hints):
# 関係のあるオブジェクト間であれば許可
db_list = settings.DATABASES.keys()
if obj1._state.db in db_list and obj2._state.db in db_list:
return True
return None
def allow_migrate(self, db, app_label, model_name=None, **hints):
# マイグレーションは default のみ
return db == 'default'
settings.py にルーターを指定
DATABASE_ROUTERS = ['routers.db_router.MasterSlaveRouter']
コメント