一、核心架构
1. 整体思路
- 主库(Master) :负责 写操作(INSERT/UPDATE/DELETE/DDL)
- 从库(Slave) :负责 读操作(SELECT)
- 主从复制:主库数据实时同步到从库
- 读写分离:应用层或中间件把读写路由到不同库
2. 优点
- 读请求压力分摊到多台从库
- 主库专注写,性能更稳定
- 从库可做备份、报表、查询,不影响主库
- 故障时可快速切换主从,提高可用性
3. 缺点
- 存在主从延迟,读到旧数据
- 架构变复杂,运维成本增加
- 需处理一致性、延迟、切换问题
二、主从复制原理(必背)
1. 流程
- 主库执行事务,写入 binlog
- 从库 IO 线程连接主库,拉取 binlog → 写入 relay log
- 从库 SQL 线程读取 relay log,重放 SQL → 实现数据一致
2. 三种复制模式
-
异步复制(默认)主库提交不等待从库,性能高,可能丢数据
-
半同步复制 (推荐生产)主库等待至少一个从库 ACK 再提交,数据更安全
-
增强半同步 等待从库落盘 relay log 再返回,更安全
3. 三种 binlog 格式
- STATEMENT:SQL 语句,体积小,可能不一致
- ROW:行数据,最安全,推荐
- MIXED:混合,自动选择
三、主从复制配置(最简模板)
1. 主库 my.cnf 关键配置
ini
server-id = 1
log_bin = mysql-bin
binlog_format = ROW
gtid_mode = ON
enforce_gtid_consistency = ON
sync_binlog = 1
innodb_flush_log_at_trx_commit = 1
# 半同步
plugin_load_add = rpl_semi_sync_master.so
rpl_semi_sync_master_enabled = 1
rpl_semi_sync_master_timeout = 1000
2. 从库 my.cnf 关键配置
ini
server-id = 2
read_only = 1
super_read_only = 1
relay_log = relay-bin
log_slave_updates = 1
gtid_mode = ON
enforce_gtid_consistency = ON
# 并行复制
slave_parallel_type = LOGICAL_CLOCK
slave_parallel_workers = 8
3. 建立主从
- 主库创建复制账号
sql
CREATE USER 'repl'@'%' IDENTIFIED BY 'Repl@123';
GRANT REPLICATION SLAVE ON *.* TO 'repl'@'%';
- 从库执行
sql
CHANGE MASTER TO
MASTER_HOST='xxx.xxx.xxx.xxx',
MASTER_USER='repl',
MASTER_PASSWORD='Repl@123',
MASTER_AUTO_POSITION=1;
START SLAVE;
- 检查状态
sql
SHOW SLAVE STATUS\G
看到 Slave_IO_Running: Yes Slave_SQL_Running: Yes 即为正常
四、读写分离实现方式
1. 应用层实现(硬编码)
- 业务代码里:
- 写走主库数据源
- 读走从库数据源
- 优点:简单、灵活
- 缺点:耦合重、维护麻烦
2. 中间件实现(生产主流)
常用工具:
- Sharding-JDBC(Java 生态最强)
- MyCat
- ProxySQL
- MaxScale
- Amoeba
通用逻辑
- 写请求 → 主库
- 读请求 → 从库
- 支持权重、负载均衡
- 支持强制走主库(如刚写完立即读)
五、读写分离核心问题
1. 主从延迟(最常见坑)
表现:刚插入 / 更新,读从库查不到
解决方案:
- 关键业务 强制走主库
- 使用半同步 + 并行复制
- 监控延迟,自动剔除延迟过高从库
- 业务设计允许短暂不一致
2. 数据一致性
- 强一致:必须走主库
- 最终一致:读写分离 + 接受短延迟
- 金融 / 订单类:尽量主库读或使用 MGR
3. 从库故障
- 中间件自动剔除不可用从库
- 读流量切到其他从库 / 主库
4. 主库故障
- 手动 / 自动切换主从
- 中间件修改路由指向新主库
六、生产最佳实践
- 一主多从:1 主 + 2~3 从
- 读多写少场景效果最好
- 必须开启 GTID,方便切换
- 必须开启 半同步复制
- 从库设置 read_only 防止误写
- 读写分离中间件做健康检查、负载均衡
- 监控:复制状态、延迟、连接数、TPS/QPS
- 刚写完立刻要读的接口,强制路由主库
七、面试高频问答
-
**读写分离解决什么问题?**分担读压力,提升数据库整体吞吐量。
-
**主从延迟怎么解决?**强制主库读、并行复制、优化大事务、中间件剔除延迟节点。
-
**半同步和异步区别?**异步不保证同步,半同步保证至少一个从库收到日志。
-
**GTID 好处?**自动定位事务位置,主从切换更简单。
-
**读写分离后怎么保证强一致?**关键读走主库,或使用 MGR 强一致集群。