前言
随着业务规模的增长,单机 MySQL 在并发能力、数据容量、可用性等方面都会逐渐遇到瓶颈。为了支撑更高的 QPS、更大的数据量以及更稳定的服务,MySQL 架构会不断演进,从单库 → 主从复制 → 读写分离 → 分库分表。
本文将从三个核心维度,系统性拆解 MySQL 的常见架构设计:
- MySQL 主从复制架构(基于 binlog)
- 主从延迟产生原因与治理方案
- 分库分表设计(以订单系统为例)
一、MySQL 主从复制架构详解
1. 为什么需要主从复制?
主从复制(Master-Slave Replication)是 MySQL 最经典、最基础的高可用与扩展方案,主要解决三个问题:
- 读性能扩展:主库写,从库读(读写分离)
- 数据冗余备份:从库作为数据副本
- 高可用基础:主库故障时可切换从库
主从复制的核心依赖:binlog(二进制日志)
2. binlog 是什么?
binlog 是 MySQL Server 层产生的日志,用于记录:
- 对数据产生变更的操作
- 如:
INSERT / UPDATE / DELETE / DDL
binlog 具备以下特性:
- 追加写(顺序 IO)
- 逻辑日志(不是物理页变化)
- 主从复制、数据恢复的基础
3. 主从复制的整体流程
MySQL 主从复制本质上是:
把主库的 binlog “传输 + 重放” 到从库
整个流程可以拆解为三个核心阶段:
阶段一:主库写入 binlog
当主库执行一条事务时:
- 执行 SQL,修改内存中的数据页
- 生成 binlog event
- 将 binlog 顺序写入 binlog 文件
- 事务提交成功
注意:
- binlog 是在事务提交阶段写入
- 先写 binlog,再提交事务(两阶段提交的一部分)
阶段二:binlog 同步到从库
从库会启动一个IO Thread:
- IO Thread 与主库建立连接
- 主库启动Binlog Dump Thread
- 主库不断将 binlog event 推送给从库
- 从库将接收到的 binlog 写入本地的Relay Log(中继日志)
此阶段本质是网络 IO + 顺序写磁盘
阶段三:从库回放 binlog(重放数据)
从库启动SQL Thread:
- 读取 Relay Log
- 按顺序解析 binlog event
- 在从库执行对应的 SQL 或行变更
- 最终与主库数据保持一致
4. 主从复制的特点总结
- 默认是异步复制
- 主库事务提交不等待从库完成
- 存在主从延迟风险
- 复制是单线程回放(MySQL 5.6 之后支持并行)
二、主从延迟:为什么会发生?如何治理?
1. 什么是主从延迟?
主从延迟指的是:
主库已经提交成功的数据,从库还未完成回放
常见表现:
- 刚写入的数据,从库查询不到
- 读写分离后出现“读到旧数据”
2. 主从延迟产生的常见原因
(1)从库 SQL 回放能力不足
- 单线程回放 binlog
- 主库写入速度 > 从库回放速度
(2)大事务 / 批量操作
- 一个大事务必须完整回放完成
- 阻塞后续 binlog
(3)从库硬件性能较弱
- IO、CPU、内存瓶颈
(4)网络抖动
- binlog 传输不稳定
3. 主从延迟的治理方案
方案一:强制走主库(最常见)
适用场景:
- 写后立即读
- 下单后查订单
做法:
- 关键读请求不走从库
- 通过代码或中间件控制
写操作 → 主库 强一致性读 → 主库 非关键读 → 从库方案二:基于 binlog 位点判断
- 记录写入时的 binlog position
- 从库读取到该 position 后再读
优点:一致性强
缺点:实现复杂,成本高
方案三:半同步复制(Semi-sync)
- 主库至少等待一个从库 ACK
- 减少数据丢失风险
- 不能完全消除延迟
方案四:并行复制(MySQL 5.7+)
- 基于库级 / 组提交的并行回放
- 明显提升从库吞吐能力
三、分库分表设计:以订单系统为例
当单库单表的数据量和 QPS 达到瓶颈时,仅靠主从复制已经不够,就需要引入分库分表。
1. 什么是分库分表?
本质:把一张大表,拆成多张小表
目标:
- 降低单表数据量
- 提升查询和写入性能
- 降低锁冲突
2. 订单系统为什么需要分库分表?
订单表通常具备以下特点:
- 数据量极大(千万 / 亿级)
- 写多读多
- 按用户、订单号频繁查询
如果全部放在一张表:
- 索引巨大
- 查询变慢
- 写入锁冲突严重
3. 分库分表的三种核心方式
垂直分表(按字段拆)
思想:
把字段多、访问频率低的列拆出去
示例:
order_base 表: order_id, user_id, status, create_time order_ext 表: order_id, address, remark, invoice_info优点:
- 减少热表字段
- 提高缓存命中率
垂直分库(按业务拆)
思想:
不同业务模块使用不同数据库
示例:
订单库 支付库 用户库优点:
- 降低库级耦合
- 易于团队拆分
水平分库分表(最核心)
思想:
按某个规则,把同一张表的数据拆到多个库 / 表
常见分片键:
- user_id
- order_id
示例(按 user_id):
order_db_0.order_0 order_db_0.order_1 order_db_1.order_0 order_db_1.order_1路由规则:
db_index = user_id % 2 table_index = user_id % 24. 分库分表带来的挑战
- 跨库 JOIN 不可用
- 全局唯一 ID 生成
- 分页、排序复杂
- 运维成本上升
因此通常会配合:
- 分布式 ID(雪花算法)
- 中间件(ShardingSphere)
- 业务层聚合
总结
MySQL 的架构演进,本质是围绕性能、容量、可用性三个目标不断拆解:
主从复制:解决读扩展与数据冗余
延迟治理:保证一致性与用户体验
分库分表:突破单机与单表瓶颈
理解这些设计,不只是为了“会用 MySQL”,而是为了在真实业务中,设计出可扩展、可演进的系统架构。