一、架构原理与方案选型
1. 读写分离核心价值
- 提升读性能:水平扩展读能力
- 保障写安全:主库专注事务处理
- 灾备容错:从库故障不影响核心业务
2. 典型部署方案
二、Django 多数据库配置
1. 基础配置(settings.py
)
DATABASES = {
'default': { # 默认数据库(主库)
'ENGINE': 'django.db.backends.mysql',
'HOST': 'master.db.example.com',
'NAME': 'mydb',
'USER': 'write_user',
'PASSWORD': 'secure_pwd'
},
'replica1': {
'ENGINE': 'django.db.backends.mysql',
'HOST': 'replica1.db.example.com',
'NAME': 'mydb',
'USER': 'read_user',
'PASSWORD': 'read_pwd'
},
'replica2': {
'ENGINE': 'django.db.backends.mysql',
'HOST': 'replica2.db.example.com',
'NAME': 'mydb',
'USER': 'read_user',
'PASSWORD': 'read_pwd'
}
}
2. 连接池优化(推荐)
# 使用 django-db-connections
DATABASES['default']['CONN_MAX_AGE'] = 300 # 5分钟连接复用
DATABASES['replica1']['CONN_MAX_AGE'] = 60
三、路由策略实现
1. 基础路由类(database_routers.py
)
import random
class PrimaryReplicaRouter:
def db_for_read(self, model, **hints):
"""读操作路由到从库"""
return random.choice(['replica1', 'replica2'])
def db_for_write(self, model, **hints):
"""写操作强制使用主库"""
return 'default'
def allow_relation(self, obj1, obj2, **hints):
"""允许跨库关系"""
return True
def allow_migrate(self, db, app_label, model_name=None, **hints):
"""迁移仅限主库"""
return db == 'default'
2. 注册路由策略(settings.py
)
DATABASE_ROUTERS = ['myproject.database_routers.PrimaryReplicaRouter']
四、高级路由场景
1. 强制主库读取(解决复制延迟)
from django.db import connections
def get_real_time_data():
"""关键数据强制主库读取"""
with connections['default'].cursor() as cursor:
cursor.execute("SELECT * FROM sensitive_table")
return cursor.fetchall()
2. 写后同步读取保障
from django.db import transaction
@transaction.atomic
def create_order(data):
order = Order.objects.create(**data) # 写主库
# 立即主库读取
return Order.objects.using('default').get(pk=order.pk)
五、生产环境注意事项
1. 主从同步监控
# 主库检查
SHOW MASTER STATUS\G
# 从库检查
SHOW SLAVE STATUS\G
2. 故障转移策略
class SmartRouter(PrimaryReplicaRouter):
def db_for_read(self, model, **hints):
"""健康检查后路由"""
alive_replicas = check_replica_health()
return random.choice(alive_replicas) if alive_replicas else 'default'
3. 性能监控指标
- 主库写
QPS
监控 - 从库复制延迟时间
- 连接池使用率
六、完整实现示例
1. 项目结构
myproject/
├── core/
│ ├── database_routers.py # 路由策略
│ └── health_check.py # 健康检查
└── myproject/
├── settings.py # 数据库配置
└── urls.py
2. 健康检查实现
# health_check.py
import MySQLdb
from django.conf import settings
def check_replica_health():
healthy = []
for alias in ['replica1', 'replica2']:
try:
conn = MySQLdb.connect(**settings.DATABASES[alias])
with conn.cursor() as cursor:
cursor.execute("SELECT 1")
healthy.append(alias)
except Exception:
pass
return healthy
七、读写分离验证方法
1. 日志追踪
# settings.py 开启查询日志
LOGGING = {
'version': 1,
'handlers': {
'console': {
'class': 'logging.StreamHandler',
},
},
'loggers': {
'django.db.backends': {
'level': 'DEBUG',
'handlers': ['console'],
}
}
}
2. 手动验证
# 写入验证
obj = MyModel.objects.create(name="test") # 主库
print(obj.pk)
# 读取验证
MyModel.objects.get(pk=obj.pk) # 随机从库
八、扩展方案推荐
1. 结合缓存层
from django.core.cache import cache
def get_with_cache(pk):
data = cache.get(f'obj_{pk}')
if not data:
data = MyModel.objects.get(pk=pk)
cache.set(f'obj_{pk}', data, 30)
return data
2. 分库分表整合
class ShardingRouter:
def db_for_read(self, model, **hints):
if model._meta.app_label == 'user':
return 'user_replica'
return super().db_for_read(model, **hints)
通过以上实现方案,可构建出企业级读写分离架构。建议在实施后持续监控数据库性能指标,并建立自动化的故障转移机制。对于需要强一致性的业务场景,可采用同步复制或应用层双读验证策略。
高级用户可结合ProxySQL等中间件实现更智能的流量调度。