트래픽량이 많아지면 DB에 접근하는 I/O 작업 시간이 길어지기 때문에 Application의 CPU 연산보다 더 큰 bottleneck이 된다.
DB 작업은 read, 즉 select가 대부분이기 때문에 read replica를 두어 read는 replica가, write는 master(default)가 하게하면 read 작업을 분산시킬 수 있다.
django에서는 multidatabase를 쓸 수 있도록 되어있다.
- Model.objects.using('{dbname}')
- Model Manager에서 .using('{dbname}')
- django.db.router로 DB Router 설정
모든 read 작업이 replica로 가는 것을 처리하기 위해서는
Router에서 db_for_read는 replica를 db_for_write는 default를 return하도록 하면 된다
이 때, write database로 설정한 default는 서드파티 라이브러리에서 db 이름을 default로 하드코딩 해놓은 사례가 있어 default에서 이름을 변경하지 않는 것이 좋다.
read replica의 이름은 변경해도 상관없다
DATABASES = {
'default': {
'NAME': 'default',
'ENGINE': 'django.db.backends.mysql',
'USER': 'mysql_user',
'PASSWORD': 'swordfish',
},
'replica1': {
'NAME': 'replica1_name',
'ENGINE': 'django.db.backends.mysql',
'USER': 'mysql_user',
'PASSWORD': 'eggs',
},
'replica2': {
'NAME': 'replica2_name',
'ENGINE': 'django.db.backends.mysql',
'USER': 'mysql_user',
'PASSWORD': 'bacon',
},
}
DATABASE_ROUTERS = ['path.to.DbRouter']
import random
class DbRouter:
def db_for_read(self, model, **hints):
"""
Reads go to a randomly-chosen replica.
"""
return random.choice(['replica1', 'replica2'])
def db_for_write(self, model, **hints):
"""
Writes always go to default.
"""
return 'default'
...
결제 등의 transaction을 관리할 때, 아직 write가 끝나지 않은 데이터에 대해 read가 이루어져 데이터의 안정성을 해치는 것을 막으려면 아래와 같이 관리하면 된다.
import random
from django.db import transaction
class DbRouter:
def db_for_read(self, model, **hints):
conn = transaction.get_connection('default')
if conn.is_atomic_block:
return 'default'
return random.choice(['replica1', 'replica2'])
def db_for_write(self, model, **hints):
"""
Writes always go to default.
"""
return 'default'
...
그리고 Aurora는 custom endpoint를 사용해서 random choice하는 database name들을 굳이 저렇게 안 늘여놓아도 된다고 한다.
참고 영상: https://www.youtube.com/watch?v=eAP8zimx05M&t=542s
'python & django & scipy' 카테고리의 다른 글
[django - google drive api] google drive api로 shared drive(공유 드라이브) 접근하기 (0) | 2022.12.28 |
---|---|
[pandas & django] gspread 사용하기 (0) | 2022.12.23 |
[pandas] google sheet 에서 데이터 가져오기 (0) | 2022.12.23 |
[python] @property, __init__ (0) | 2022.08.31 |
[python] self와 cls의 차이 / instance method, static method, class method의 차이 (0) | 2022.08.31 |