数据库读写分离

数据库读写分离通过 Master 承担写请求、Slave 承担读请求来扩展高并发读能力,但主从复制会带来主从延迟问题,因此需要根据业务一致性要求选择同步复制、强制读主或会话分离等方案,在读性能、写性能和数据一致性之间做权衡。

一、核心主线

高并发读场景的第一种通用方案:数据库读/写分离

大多数互联网应用都是读多写少:

1
2
3
刷帖请求 > 发帖请求
浏览商品请求 > 下单请求
浏览内容请求 > 发布内容请求

因此,数据库承受的高并发压力通常主要来自读请求。

读写分离的核心思路是:

1
2
3
4
写请求 → 写库 Master
读请求 → 读库 Slave

Master 通过主从复制将数据同步给 Slave

这样可以把大量读请求从主库中分流出去,降低数据库访问压力,缩短请求响应时间。


二、读写分离架构

1. 基本结构

读写分离通常基于数据库主从复制实现:

1
2
3
4
5
6
7
业务服务器

数据访问层
├─ 写请求 → Master
└─ 读请求 → Slave

Master ──主从复制──> Slave

其中:

  • Master:数据库主节点,作为写库,处理写请求;
  • Slave:数据库从节点,作为读库,处理读请求;
  • 主从复制:Master 将写入后的最新数据同步到 Slave。

一个 Master 可以连接多个 Slave,从而扩展读能力。

2. 读写分离的价值

读写分离主要解决两个问题:

  1. 降低主库压力:读请求不再全部打到 Master;
  2. 提升读吞吐量:多个 Slave 可以共同承担读请求。

适合场景:

  • 读多写少;
  • 读请求压力明显高于写请求;
  • 可以容忍一定程度的主从同步延迟;
  • 业务读写路径比较清晰。

三、读写请求路由方式

读写分离的关键问题是:

谁来判断一个请求应该访问 Master 还是 Slave?

本节介绍了两种常见路由方式。


1. 基于数据库 Proxy 的方式

在业务服务和数据库之间增加数据库代理层:

1
2
3
4
5
业务服务
↓ SQL 请求
数据库 Proxy
├─ 写 SQL → Master
└─ 读 SQL → Slave

Proxy 会根据 SQL 类型进行路由:

SQL 类型 路由目标
insert Master
delete Master
update Master
select Slave

常见实现包括:

  • MySQL-Proxy;
  • MyCat;
  • MySQL-Router。

优点

  • 读写分离逻辑集中在 Proxy;
  • 业务代码改造较少;
  • 对业务服务相对透明;
  • 适合统一治理数据库访问。

缺点

  • Proxy 本身可能成为性能瓶颈;
  • Proxy 需要保证高可用;
  • SQL 解析和路由逻辑可能增加复杂度;
  • 业务侧对细粒度路由控制能力较弱。

2. 基于应用内嵌的方式

读写路由逻辑直接嵌入业务服务进程中:

1
2
3
业务服务内部数据库访问框架
├─ 写请求 → Master
└─ 读请求 → Slave

常见数据库连接框架或组件包括:

  • gorm;
  • shardingjdbc。

优点

  • 少一层网络代理;
  • 路由控制更灵活;
  • 可以结合业务语义做更精细的读写选择;
  • 不会引入中心化 Proxy 瓶颈。

缺点

  • 业务服务需要引入读写分离逻辑;
  • 多语言、多框架环境下治理成本更高;
  • 路由规则分散在应用侧,统一管理难度较大。

四、主从延迟问题

1. 主从延迟是什么

读写分离依赖主从复制,而主从复制通常不是瞬时完成的。

当 Master 写入成功后,Slave 可能还没有同步到最新数据:

1
2
3
4
5
写请求 → Master 写入成功

主从复制存在延迟

读请求 → Slave 读取不到最新数据

这就是主从延迟

2. 主从延迟带来的问题

主从延迟会造成短时间内的主从数据不一致。

典型表现:

  • 用户刚发布内容,刷新页面却看不到;
  • 用户刚修改资料,读取时还是旧资料;
  • 用户刚完成操作,下一个查询请求读到了旧状态。

所以,读写分离提升了读性能,但引入了一致性问题。


五、主从延迟的三种解决方案

1. 同步数据复制

原理

默认主从复制通常是异步模式:

1
Master 写完数据 → 直接返回成功

同步复制则要求:

1
2
3
4
5
Master 写完数据

等待全部 Slave 收到数据

再返回写入成功

优点

  • Master 和 Slave 能在写操作成功后同时读取到最新数据;
  • 主从一致性更强;
  • 业务服务改造较少。

缺点

  • Master 必须等待全部 Slave;
  • 写请求延迟明显增加;
  • 数据库吞吐量下降;
  • 某个 Slave 慢或异常会影响整体写入。

适用场景

同步复制实用价值较低,更适合:

  • 低并发场景;
  • 对一致性要求极高;
  • 写入吞吐压力不大的业务。

2. 强制读主

原理

不同业务场景对主从延迟的容忍度不同。

对于不能容忍主从延迟的读请求,直接路由到 Master:

1
2
3
普通读请求 → Slave
强一致读请求 → Master
写请求 → Master

示例

用户 A 刚发布一条状态:

  • A 自己刷新个人主页时,应该立刻看到新状态;
  • 好友 B 查看 A 的主页时,可以暂时看不到这条新状态。

因此:

1
2
A 自己读自己的新状态 → 强制读 Master
B 查看 A 的状态 → 可以读 Slave

优点

  • 针对关键场景保证读到最新数据;
  • 不需要所有读请求都访问主库;
  • 在一致性和读扩展之间做平衡。

缺点

  • 需要识别哪些场景不能容忍延迟;
  • 强制读主过多会削弱读写分离效果;
  • 业务逻辑复杂度增加。

3. 会话分离

原理

如果某个会话刚执行过写操作,那么在接下来很短的一段时间内,该会话的读请求临时路由到 Master。

1
2
3
4
5
用户会话发生写操作

短时间内该会话读请求强制读 Master

超过主从复制延迟窗口后恢复读 Slave

设计关键

强制读主的时间窗口应略高于主从复制延迟。

例如:

1
2
3
主从复制通常延迟 200 ms

会话写入后 300 ms 内读主

这样可以尽量覆盖主从数据复制的实际延迟时间。

优点

  • 保证“自己写的数据自己立刻可见”;
  • 不需要所有用户都强制读主;
  • 对主库压力影响相对可控。

缺点

  • 需要维护会话状态;
  • 需要估算合理的主从延迟时间窗口;
  • 如果实际延迟超过窗口,仍可能读到旧数据;
  • 实现复杂度高于普通读写分离。

六、三种主从延迟方案对比

方案 核心思路 优点 缺点 适用场景
同步数据复制 Master 等所有 Slave 收到数据后再返回 一致性强,业务改造少 写延迟高,吞吐下降 低并发、强一致
强制读主 不能容忍延迟的读请求访问 Master 精准保证关键读一致性 需要业务识别场景,读主过多会压垮 Master 局部强一致场景
会话分离 写后短时间内,同一会话读 Master 保证用户读到自己的写入 需要维护会话和时间窗口 写后读一致性场景

七、核心架构思想

  1. 大部分互联网系统是读多写少,数据库压力主要来自读请求。
  2. 读写分离通过 Master 处理写、Slave 处理读来扩展读能力。
  3. 读写分离通常依赖数据库主从复制。
  4. 读写路由可以放在数据库 Proxy,也可以放在应用内部。
  5. Proxy 方式对业务更透明,但需要治理代理层的性能和高可用。
  6. 应用内嵌方式更灵活,但会增加业务代码和框架治理复杂度。
  7. 读写分离的核心副作用是主从延迟。
  8. 主从延迟会导致写后立即读时读取不到最新数据。
  9. 同步复制增强一致性,但牺牲写性能和吞吐量。
  10. 强制读主适合不能容忍延迟的关键业务场景。
  11. 会话分离适合保证用户“自己写后自己可见”。
  12. 读写分离的本质权衡是:读性能扩展与数据一致性之间的平衡。

© 2026 DadaVinCi's Blog

Elegant theme by Shiro · Made by Acris with ❤️