导航菜单

读写分离

场景

一年后,用户数突破百万。

数据规模:
- 日调用量: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 特别火,我需要处理热点数据

搜索