DjangoにRSDのリードレプリカを導入する

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']
よかったらシェアしてね!
  • URLをコピーしました!
  • URLをコピーしました!

コメント

コメントする


reCaptcha の認証期間が終了しました。ページを再読み込みしてください。

目次