1. 主从复制
定义:主库(Master)将所有写操作记录到二进制日志(binlog),从库(Slave)通过专属线程拉取主库binlog,写入本地中继日志(relay log),再重放日志实现数据同步,是MySQL高可用、高并发的基础。
核心价值:
- 数据备份:从库作为主库的备份节点,避免单点故障导致数据丢失
- 读写分离:为后续读写分离提供基础,分担主库读压力
- 故障转移:主库故障时,可快速切换至从库,保障服务连续性
2. 读写分离
定义:通过中间件或应用层配置,将写请求(INSERT/UPDATE/DELETE/DDL)路由至主库,读请求(SELECT)路由至从库,实现读写负载分离。
核心价值:
- 提升读吞吐量:多从库分担读请求,解决高并发下读压力瓶颈
- 降低主库负载:主库仅处理写请求,减少资源占用,提升写性能
- 支撑高并发:适配业务中"读多写少"的常见场景(如电商、博客)
二、主从复制深度解析
1. 核心原理
- 主库写日志:主库执行完写操作后,将操作顺序写入二进制日志(binlog),确保日志的完整性和顺序性。
- 从库拉取日志:从库的I/O线程主动连接主库,请求获取binlog;主库的binlog dump线程将binlog内容逐步发送给从库,从库接收后写入本地中继日志(relay log)。
- 从库重放日志:从库的SQL线程读取中继日志中的内容,逐行执行对应操作,将主库的数据变更同步到从库,最终实现主从数据一致。
2. 关键组件与线程
|-----------------|------------------------------------|------|
| 组件/线程 | 核心作用 | 所在节点 |
| 二进制日志(binlog) | 记录主库所有数据变更操作(写、改、删、DDL),是同步的核心依据 | 主库 |
| 中继日志(relay log) | 暂存从库拉取的主库binlog,避免直接操作binlog影响同步效率 | 从库 |
| binlog dump线程 | 响应从库I/O线程的请求,推送binlog内容至从库 | 主库 |
| I/O线程 | 连接主库,拉取binlog并写入本地relay log | 从库 |
| SQL线程 | 读取relay log,重放日志中的操作,同步主库数据 | 从库 |
3. 三种复制类型对比(重点记ROW)
|-------------|-------------------------------|-----------------|----------------------------|----------------------|
| 复制类型 | 核心原理 | 优点 | 缺点 | 适用场景 |
| 语句复制(SBR) | 记录主库执行的SQL语句,从库重复执行相同SQL | binlog体积小,同步效率高 | 可能出现数据不一致(如NOW()、RAND()函数) | 简单测试场景、非核心业务 |
| 行复制(ROW) | 记录每行数据的变更内容(如某行数据从A改为B) | 数据同步精准,无一致性问题 | binlog体积大,占用更多磁盘和带宽 | 生产环境(MySQL 8.0默认此类型) |
| 混合复制(MIXED) | 自动切换SBR和ROW,简单语句用SBR,复杂语句用ROW | 兼顾性能与一致性 | 逻辑复杂,排查问题难度大 | 通用场景,需平衡性能与一致性 |
三、读写分离架构与实现方案
1. 经典架构(最常用)
核心架构:1主2从 + 中间件(推荐ProxySQL)
流程:应用 → 中间件 → 写请求路由至主库,读请求负载均衡至多个从库
示意图:应用 → ProxySQL/MyCat → 主库(写)、从库1(读)、从库2(读)
2. 主流实现方案对比(重点记ProxySQL)
|--------------|-------------------------------|----------------------|
| 实现方案 | 核心特点 | 适用场景 |
| ProxySQL | 高性能、轻量、原生支持MGR、路由规则灵活、可监控复制状态 | 生产环境、高可用需求、读写分离+故障转移 |
| MyCat | 功能强大,支持读写分离、分库分表、多租户,兼容性好 | 复杂分布式架构、需要分库分表的业务 |
| MySQL Router | 官方轻量代理,无缝集成MGR,配置简单 | 官方生态、轻量需求、MGR集群 |
| 应用层实现 | 代码中区分读写数据源,无需部署中间件 | 小型应用、访问量低、无中间件部署条件 |
3. ProxySQL核心配置
(1)添加后端主从节点
|---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
| sql -- 写组(hostgroup_id=10,主库) INSERT INTO mysql_servers (hostgroup_id, hostname, port, weight) VALUES (10, '192.168.10.103', 3306, 100); -- 读组(hostgroup_id=20,从库) INSERT INTO mysql_servers (hostgroup_id, hostname, port, weight) VALUES (20, '192.168.10.101', 3306, 100), (20, '192.168.10.102', 3306, 100); -- 生效配置(加载到运行时并保存到磁盘) LOAD MYSQL SERVERS TO RUNTIME; SAVE MYSQL SERVERS TO DISK; |
(2)配置读写分离路由规则
|----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
| sql -- 规则1:SELECT ... FOR UPDATE(锁表读)走写组(主库) INSERT INTO mysql_query_rules (rule_id, active, match_pattern, destination_hostgroup, apply) VALUES (1, 1, '^SELECT.*FOR UPDATE$', 10, 1); -- 规则2:普通SELECT走读组(从库) INSERT INTO mysql_query_rules (rule_id, active, match_pattern, destination_hostgroup, apply) VALUES (2, 1, '^SELECT', 20, 1); -- 生效规则 LOAD MYSQL QUERY RULES TO RUNTIME; SAVE MYSQL QUERY RULES TO DISK; |
四、常见问题与解决方案
1. 主从复制常见问题
|------------------------------|---------------------------|------------------------------------------------------------------------------------|
| 问题现象 | 核心原因 | 解决方案 |
| Slave_IO_Running: Connecting | 网络不通、复制账号密码错误、主库IP/端口配置错误 | 1. 检查主从网络(telnet/nc测试3306端口);2. 验证复制账号权限;3. 重新配置CHANGE MASTER TO |
| Slave_SQL_Running: No | SQL执行冲突(如主键重复)、日志重放失败 | 1. 跳过错误事务:SET GLOBAL sql_slave_skip_counter = 1; START SLAVE; 2. 排查数据不一致,手动同步后重启复制 |
| 主从延迟大 | 单线程复制、主库大事务(如批量插入)、从库性能差 | 1. 开启从库多线程复制(slave_parallel_workers > 1);2. 拆分大事务;3. 优化从库硬件配置 |
2. 读写分离常见问题
|----------|-----------------------|-------------------------------------------------------|
| 问题现象 | 核心原因 | 解决方案 |
| 读请求数据不一致 | 主从延迟(写主库后,从库未同步完成就读取) | 1. 核心业务读请求路由至主库;2. 设置延迟阈值,超过阈值自动切换至主库;3. 优化主从同步效率 |
| 从库宕机 | 从库硬件故障、服务异常 | 1. 中间件自动剔除故障从库;2. 部署多从库冗余;3. 重启从库后重新同步 |
| 事务内读走从库 | 事务跨节点,写主库后读从库,数据未同步 | 1. 开启事务持久化(transaction_persistent=1);2. 事务内所有读请求路由至主库 |
五、进阶架构:MGR 读写分离
1. MGR(Group Replication)核心优势
- 强一致性:基于Paxos协议,保证集群内所有节点数据一致,避免主从复制的一致性问题
- 自动故障转移:主节点失效后,集群自动选举新主,无需人工干预,提升可用性
- 原生读写分离:写请求仅路由至主节点,读请求可分发至任意从节点,适配高并发
2. MGR + MySQL Router 架构
流程:应用 → MySQL Router(6446读写端口/6447只读端口) → MGR集群(主节点写,从节点读)
优势:配置简单、无缝集成、官方维护,适合生产环境高可用需求
六、运维最佳实践
1. 基础配置要求
- 主库:开启binlog(log_bin=ON)、设置唯一server-id(如1)、binlog格式设为ROW
- 从库:开启relay log、设置唯一server-id(如2、3)、配置read_only=1(禁止普通用户写入)
2. 性能优化
- 开启半同步复制:主库配置rpl_semi_sync_master=1,从库配置rpl_semi_sync_slave=1,兼顾性能与一致性
- 从库多线程复制:设置slave_parallel_workers=4(根据CPU核心调整),提升同步效率
- 优化binlog:设置binlog_expire_logs_seconds=86400(自动清理1天前的binlog),避免磁盘占满
3. 监控与维护
- 监控工具:Prometheus+Grafana(监控主从状态、延迟)、pt-heartbeat(精准监控主从延迟)
- 定期检查:每日查看复制状态(show slave status\G)、清理过期binlog、检查账号权限