读写分离
场景
一年后,用户数突破百万。
数据规模:
- 日调用量:100 万次
- 写操作:10 万次/天(日志、统计)
- 读操作:100 万次/天(查询、验证)
- 读写比例:1:10数据库开始出现瓶颈。
问题分析
性能监控:
- 数据库 CPU:85%
- 慢查询:每天 500+ 次
- 主库延迟:平均 200ms
瓶颈分析:
- 大部分请求是读操作
- 写操作相对较少
- 主库承担所有压力解决方案:读写分离
架构设计
应用层
│
├─ 写操作 → 主库 (Master)
│ │
│ ├─ 从库 1 (Slave) ◄─ 读操作
│ ├─ 从库 2 (Slave) ◄─ 读操作
│ └─ 从库 3 (Slave) ◄─ 读操作实现读写分离
数据库配置
主库配置 (my.cnf)
[mysqld]
server-id = 1
log-bin = mysql-bin
binlog_format = ROW从库配置 (my.cnf)
[mysqld]
server-id = 2 # 每个从库不同
relay-log = mysql-relay-bin
read-only = 1应用层实现
class DatabaseRouter:
"""数据库路由器"""
def __init__(self):
self.master = pymysql.connect(
host='master-db.internal',
user='api_user',
password='password',
database='api_platform'
)
self.slaves = [
pymysql.connect(
host=f'slave-{i}.internal',
user='api_user',
password='password',
database='api_platform'
)
for i in range(1, 4)
]
self.current_slave = 0
def get_master_connection(self):
"""获取主库连接(写操作)"""
return self.master
def get_slave_connection(self):
"""获取从库连接(读操作)"""
# 轮询选择从库
slave = self.slaves[self.current_slave]
self.current_slave = (self.current_slave + 1) % len(self.slaves)
return slave
db_router = DatabaseRouter()
# 使用示例
def get_user(user_id):
"""读操作:使用从库"""
conn = db_router.get_slave_connection()
cursor = conn.cursor()
cursor.execute('SELECT * FROM users WHERE id = %s', (user_id,))
return cursor.fetchone()
def update_user(user_id, data):
"""写操作:使用主库"""
conn = db_router.get_master_connection()
cursor = conn.cursor()
cursor.execute('UPDATE users SET ... WHERE id = %s', (user_id,))
conn.commit()主从同步监控
延迟监控
def check_replication_lag():
"""检查主从延迟"""
with db_router.get_slave_connection() as conn:
cursor = conn.cursor()
cursor.execute('SHOW SLAVE STATUS')
status = cursor.fetchone()
lag = status['Seconds_Behind_Master']
if lag > 10:
send_alert(f'Replication lag: {lag} seconds')
return lag
# 定时检查
scheduler.add_job(
check_replication_lag,
'interval',
seconds=60,
id='check_replication'
)效果验证
优化前
主库负载:
- QPS:2000
- CPU:85%
- 响应时间:200ms优化后
主库(Master):
- QPS:200(仅写操作)
- CPU:25%
- 响应时间:50ms
从库(Slaves):
- 总 QPS:1800(读操作分散)
- 平均 CPU:30%
- 平均响应时间:80ms本节小结
✅ 完成的工作:
- 实现了 MySQL 主从复制
- 实现了应用层读写分离
- 添加了延迟监控
✅ 效果:
- 主库负载降低 90%
- 查询性能提升 3 倍
- 系统整体吞吐量提升
🎯 下一步:某个 API 特别火,我需要处理热点数据
