장고 - 멀티 데이터베이스 사용

장고의 멀티데이터베이스 기능


  • 인프라를 스케일링할 때 데이터베이스도 역시 스케일링을 고려해야 한다.
  • 데이터베이스는 동기화 문제가 발생하므로 웹 서버 인스턴스처럼 아웃 스케일링 방식을 쉽게 사용할 수 없으나,
  • 대부분의 데이터베이스 시스템은 마스터와 읽기전용 슬레이브 데이터베이스 형태를 지원해준다.
  • 아마존 인프라를 사용하면 이것도 쉽게 사용할 수 있다.
  • 마스터 베이스에 읽기전용 서버를 추가하면 각각의 데이터베이스를 언제 사용할지 결정해야 한다.
  • 보통은 쓰기 쿼리와 읽기 쿼리를 구분해서 어느 데이터베이스를 사용할지 결정하지만,
  • 장고에서는 ORM을 사용하므로 쿼리를 구분해서 분기를 할 수 없다.
  • 이를 위해 장고는 멀티데이터베이스를 위한 라우터 기법을 제공한다.
  • 멀티데이터베이스를 사용하면 데이터베이스의 병목 현상을 줄일 수 있다.
  • 라우팅 기법을 응용하면 모델별로도 다른 데이터베이스를 사용하게 할 수 있다.
  • 특히 다른 서비스에서 갖고 있는 유저 정보를 공유해서 활용하고 싶다면
  • 데이터베이스 라우팅을 사용하여 해당 정보를 기준으로 사용할 수 있다.
  • 아래 절차를 따라 멀티 데이터베이스를 셋팅하고 라우팅을 해보자.

멀티데이터베이스 사용 방법


1. AWS > 데이터베이스 생성

  • 새로운 PostgreSQL 데이터베이스 생성
    • AWS > RDS 에서 새 인스턴스 만들기에서 PostgreSQL 선택하고 [다음 단계] 버튼 클릭
  • 10.x 버전 선택(PostgreSQL 9.3.5 이상부터 읽기 전용 복제본 사용 가능)
  • 용량은 20Gib 정도로 설정하고 관리자 계정 정보 입력 후 [다음 단계] 버튼 클릭
  • 퍼블릭 액세스 가능성 ‘예’로 선택
  • 데이터베이스 옵션에서 데이터베이스 이름 입력
  • 멀티데이터베이스를 위해 읽기 전용 복제본을 만들려면 백업 기능이 활성화되어 있어야 한다.
  • 백업 보존 기간을 1일 이상으로 설정
  • 성능 개선 도우미는 비활성화(필수 옵션 아님)
  • 유지 관리 옵션도 적절히 선택하고 [데이터베이스 생성] 버튼 클릭
  • 인스턴스 생성이 완료되면 데이터베이스 셋팅 진행하고 migrate 명령 실행

2. 데이터베이스 복제본 생성

  • 인스턴스 목록에서 원하는 데이터베이스를 선택하고 상단 메뉴에서 작업 > 읽기 복제본 생성 클릭
  • 읽기 전용 복제본 생성 창이 나타나면 퍼블릭 액세스 가능 부분에서 ‘예’를 선택
  • 설정 부분의 데이터베이스 식별자를 적절히 입력
  • [읽기 전용 복제본 생성] 버튼 클릭
  • 상기 과정 반복하여 한개 복제본 추가 생성

3. 장고 설정부분에 데이터베이스 정보 추가

  • 프로젝트 > settings.py에 데이터베이스 정보 추가
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    DATABASES = {
    'default': {
    'ENGINE': 'django.db.backends.postgresql_psycopg2',
    'NAME': 'DB 이름',
    'USER': '사용자 아이디',
    'PASSWORD': '비밀번호',
    'HOST': '엔드포인트',
    'PORT': '5432',
    },
    'read1': {
    'ENGINE': 'django.db.backends.postgresql_psycopg2',
    'NAME': 'DB 이름',
    'USER': '사용자 아이디',
    'PASSWORD': '비밀번호',
    'HOST': '엔드포인트',
    'PORT': '5432',
    },
    'read2': {
    'ENGINE': 'django.db.backends.postgresql_psycopg2',
    'NAME': 'DB 이름',
    'USER': '사용자 아이디',
    'PASSWORD': '비밀번호',
    'HOST': '엔드포인트',
    'PORT': '5432',
    },

4. 라우트 클래스 생성하여 추가

  • 데이터베이스 정보 추가했으나, 자동으로 쓰기, 읽기 데이터베이스를 분기하여 사용하는 것이 아니고, 라우터 클래스를 만들어서 추가해야 한다.
  • 프로젝트 > master_slave_router.py 파일 추가 및 아래 코드 입력
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    import random
    class MasterSlaveRouter:
    def db_for_read(self, model, **hints):
    return random.choice(['read1', 'read2'])

    def db_for_write(self,model,**hints):
    return 'default' # return None

    def allow_relation(self,obj1,obj2,**hints):
    db_list = ('default', 'read1', 'read2')
    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):
    return True

5. 생성한 라우터를 장고 설정부분에 추가

  • 프로젝트 > settings.py
    1
    2
    3
    DATABASE_ROUTERS = [
    'config.master_slave_router.MasterSlaveRouter',
    ]

6. 해당 기능이 잘 동작하는지 django-debug-toolbar 설치하여 확인

  • 관리자페이지 > debug toolbar의 SQL 선택
    • 사용하는 데이터베이스 확인 가능

다른 서비스에서 갖고 있는 유저 정보를 공유해서 활용하고 싶은 경우

1. 유저 정보를 담고 있는 데이터베이스 정보를 장고 설정부분에 추가

  • 프로젝트 > settings.py
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    DATABASE = {
    'default': {
    'ENGINE': 'django.db.backends.postgresql_psycopg2',
    'NAME': 'DB 이름',
    'USER': '사용자 아이디',
    'PASSWORD': '비밀번호',
    'HOST': '엔드포인트',
    'PORT': '5432',
    },
    'read1': {
    'ENGINE': 'django.db.backends.postgresql_psycopg2',
    'NAME': 'DB 이름',
    'USER': '사용자 아이디',
    'PASSWORD': '비밀번호',
    'HOST': '엔드포인트',
    'PORT': '5432',
    },
    'read2': {
    'ENGINE': 'django.db.backends.postgresql_psycopg2',
    'NAME': 'DB 이름',
    'USER': '사용자 아이디',
    'PASSWORD': '비밀번호',
    'HOST': '엔드포인트',
    'PORT': '5432',
    },
    'user': {
    'ENGINE': 'django.db.backends.postgresql_psycopg2',
    'NAME': 'DB 이름',
    'USER': '사용자 아이디',
    'PASSWORD': '비밀번호',
    'HOST': '엔드포인트',
    'PORT': '5432',
    }
    }

2. 유저 정보 데이터베이스를 위한 라우터 추가

  • 프로젝트 > user_router.py 파일 추가 및 아래 코드 입력
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    from django.conf import settings

    class UserRouter:
    def db_for_read(self,model,**hints):
    if model._meta.model_name == 'user':
    return 'user'
    return None

    def db_for_write(self,model,**hints):
    if model._meta.model_name == 'user':
    return 'user'
    return None

    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):
    return True

3. 장고 설정부분에 라우터 추가

  • 프로젝트 > settings.py
    1
    2
    3
    4
    DATABASE_ROUTERS = [
    'config.user_router.UserRouter', # 라우터는 입력한 순서대로 실행된다.
    'config.master_slave_router.MasterSlaveRouter',
    ]

4. 관리자 페이지의 유저 모델 관리 페이지에서 쿼리 잘 실행되는지 확인