这个话题是数据库架构演进的基础课题。结合搜索结果,我来展开"主从复制扩展"这个系列第一部分的完整框架。
---
一、先厘清一个关键认知
有一篇文章的开篇概括得非常到位:[citation:26.3]
主从复制、读写分离、分库分表这三板斧,就是数据库从单机走向分布式架构时最经典的三个台阶。很多人把它们混为一谈,但实际定位完全不同:
> - 主从复制解决的是高可用
读写分离解决的是读压力的横向扩展
分库分表解决的是数据量和并发量双双超出单机承载上限
主从复制自身不直接解决"扩展"问题——它解决的是数据冗余和可用性。但它是读写分离的前提(得有从库才能把读分流),也是分库分表的基础设施(每个分片内部仍然需要主从复制来保证高可用)。
---
二、主从复制的核心架构
2.1 标准流程
主库 Master → binlog → 网络传输 → 从库 Slave
├─ I/O 线程:接收 binlog → relay log
└─ SQL 线程:重放 relay log → 数据同步
主库写入二进制日志(binlog),从库通过一个 I/O 线程把 binlog 拉到本地写入中继日志(relay log),再由 SQL 线程逐条重放。[citation:26.5]
2.2 三种同步模式
| 模式 | 写入延迟 | 数据安全 | 适用场景 |
|:----:|:-------:|:-------:|---------|
| 异步复制(默认) | 最低 | 最低(主库挂了可能丢数据) | 读多写少,允许少量数据丢失 |
| 半同步复制 | 中等 | 较高(至少一个从库收到才返回) | 对数据一致性要求较高的业务 |
| 全同步复制 | 最高 | 最高(所有从库都写入才返回) | 金融级场景(但性能代价极大) |
2.3 GTID 复制 vs 传统位点复制
| 对比项 | 传统位点复制 | GTID 复制 |
|-------|:----------:|:---------:|
| 同步依据 | binlog 文件名 + 偏移量 | 全局唯一事务 ID(GTID) |
| 主从切换 | 需手动找位点,容易出错 | 自动定位,切换更可靠 |
| 并行复制 | 需额外配置 | 天然支持,效率更高 |
| 使用建议 | 已有存量系统 | 新系统首选 |
---
三、从主从复制到读写分离
3.1 为什么需要读写分离
单机数据库的瓶颈通常是读流量远大于写流量。一台主库扛着全部读请求时,CPU 和 IO 很容易被打满。
传统模式(主库扛所有):
所有请求 → 主库 → CPU 100% → 写入也变慢
读写分离模式:
写请求 → 主库(专注写入)
读请求 → 从库(水平扩展读能力)
3.2 实现方式
| 方案 | 代表技术 | 优点 | 缺点 |
|------|---------|------|------|
| 应用层直连 | 代码中维护多数据源 | 轻量、无额外组件 | 耦合度高,扩展需改代码 |
| 中间件代理 | ShardingSphere / ProxySQL / MaxScale | 对应用透明,集中管理 | 引入额外延迟和维护成本 |
| 云托管 | 云 RDS 的只读实例 | 零运维 | 厂商锁定 |
3.3 关键痛点
主从延迟是读写分离最主要的风险。[citation:26.8]
我曾遇到过一个从库因为大事务导致延迟达到 6 小时,最终只能重建同步。
生产环境通常按业务容忍度分级处理:强一致性读强制走主库;弱一致性读走从库。
---
四、扩展的边界:什么时候该从"主从复制"走到下一步
这是一个很实用的判断框架:
graph TD
A[当前数据库状态] --> B{读压力 > 写压力?}
B -->|是| C{读压力大到主库 CPU 高?}
C -->|否| D[加从库 + 读写分离]
C -->|是| E{单表数据量 > 500万?}
E -->|否| D
E -->|是| F[水平分片/分库分表]
B -->|否| G{写压力大?}
G -->|是| H{主库 IO 打满?}
H -->|否| I[优化SQL + 缓存]
H -->|是| J[分库分表 + 分布式事务]
关键观察点来自搜索结果:[citation:26.9]
加了两台机器做主从复制后,写入依然卡顿——因为瓶颈不在机器数量,而在所有写都压在同一张主库上。
---
五、配置要点
主库配置
[mysqld]
server-id = 1
log_bin = mysql-bin
binlog_format = ROW # 建议用 ROW 格式,一致性最好
sync_binlog = 1 # 每次事务提交都刷盘
binlogdodb = your_db # 只复制指定库(可选)
从库配置
[mysqld]
server-id = 2
relay_log = mysql-relay-bin
read_only = ON # 防止从库被误写入
logslaveupdates = ON # 级联复制时需要
建立复制
-- 传统位点方式
CHANGE MASTER TO
MASTER_HOST='192.168.1.100',
MASTER_USER='repl',
MASTER_PASSWORD='password',
MASTERLOGFILE='mysql-bin.000001',
MASTERLOGPOS=154;
START SLAVE;
-- GTID 方式(推荐)
CHANGE MASTER TO
MASTER_HOST='192.168.1.100',
MASTER_USER='repl',
MASTER_PASSWORD='password',
MASTERAUTOPOSITION=1;
START SLAVE;
-- 检查同步状态
SHOW SLAVE STATUS\G
-- 关注:SlaveIORunning: Yes
-- SlaveSQLRunning: Yes
-- SecondsBehindMaster: 0
---
六、常见问题与排查
| 症状 | 可能原因 | 排查方向 |
|------|---------|---------|
| SlaveIORunning: Connecting | 网络不通 / 用户名密码错 | ping + CHANGE MASTER 重新配置 |
| SlaveSQLRunning: No | relay log 中有 SQL 错误 | SHOW SLAVE STATUS 看 LastError;SET GLOBAL SQLSLAVESKIPCOUNTER = 1 跳过 |
| SecondsBehindMaster 持续上升 | 大事务 / 从库性能不足 | 对大事务拆分批操作;升级从库硬件 |
| 主从数据不一致 | binlog_format 为 STATEMENT | 改用 ROW 格式 + pt-table-checksum 校验 |
---
七、本系列的后续方向
"主从复制扩展"这个命题至少还有以下几个方向值得深入:
主从复制扩展(二)——级联复制与多主架构:当从库数量超过 10 个时,主库的 binlog 分发会成为瓶颈,级联复制或多主环形复制可以解决
只读实例的在线扩展和缩容:如何在不停服的情况下增加/移除从库
跨地域复制与延迟优化:异地多活的延迟治理
从主从复制到分布式数据库的平滑演进:从 MGR 到 TiDB 的过渡路径
你是想继续深入某个具体方向,还是需要我帮你跑一个 Docker 环境下的主从复制搭建过程来把配置落地?
0 评论