高并发性能YUEXIAN INSIGHTS

数据库读写分离,先定义哪些读取允许落后

面向订单、会员、内容和企业系统,说明主库与只读副本的查询分流、复制延迟、读后写一致性、长查询隔离和故障切换验收。

本文目录
先看结论

读写分离不是把所有 SELECT 发到副本,而是按新鲜度和故障语义路由

先为订单确认、权限校验、商品浏览、历史报表等读取标注可接受的新鲜度,再决定读主库、读副本或等待指定写入已回放。异步复制天然存在可测延迟,连接级轮询也不等于读后写一致;当副本落后、查询冲突或不可用时,应按业务选择回主库、返回处理中、使用有时间标识的旧值或受控失败。上线验收要同时覆盖写入压力、复制回放、长查询、连接路由、故障提升和旧主库隔离,证明减轻主库读取的同时没有破坏业务正确性。

按读取的新鲜度与失败后果选择路由

读取类型建议路由与条件错误分流的后果
写后立即确认订单创建、资料修改、权限变更后需要马上看到结果,优先读主库或等待对应提交已回放副本尚未回放,用户误以为提交失败并重复操作
一般查询展示允许明确的短暂陈旧,副本延迟在业务预算内并有超限回退只设连接轮询,不检查副本位置与健康,页面随机新旧跳变
历史报表导出可使用固定数据截止时间,限制并发、扫描量与运行窗口长查询阻碍副本回放或争用 I/O,使线上查询一起变旧或被取消
关键授权与库存判断由权威数据和受约束写入路径决定,不能把陈旧副本作为最终事实撤销后的权限仍可用,或按过期库存继续受理业务
01

适用边界:读多不等于一定需要读写分离

这份方法适用于单一写入主库配合一个或多个只读副本的系统。若瓶颈来自低效查询、缺失索引、返回数据过大或应用重复读取,增加副本会复制同样的昂贵工作;写竞争、锁冲突和热点更新也不会因读副本自动消失。

先用慢查询、锁等待、连接池、磁盘与 CPU 指标确认主库读取确实占用关键资源,再按业务路径统计可分流比例。只读副本会增加实例、连接路由、监控、备份和故障处置成本,也可能使问题从“主库慢”变成“用户读到旧数据”。

副本不是备份的同义词。错误删除和错误更新通常也会被复制;备份仍需独立保留、恢复验证和保留周期。若目标主要是灾难恢复,应先定义恢复点与恢复时间,再判断同一套副本是否同时适合承载查询。

  • 保留优化前的主库查询、写入、锁与资源基线。
  • 估算真正可分流的读取,而不是按所有 SELECT 数量计算收益。
02

先给读取标注新鲜度、权威来源与失败语义

把接口按业务结果分类:哪些必须看到刚提交的数据,哪些允许落后数秒或一个批次,哪些报表可以明确截止时间。新鲜度不能只写“尽量实时”,需要说明超过预算时用户看到什么、系统转到哪里。

写后立即读是最常见陷阱。用户完成下单、改手机号或提交审批后,如果下一次查询随机进入尚未回放的副本,页面可能显示不存在或旧状态。可在有限会话窗口读主库,或携带能够代表本次提交的复制位置并等待目标副本追上;具体能力与等待方式需按数据库、驱动和代理验证。

权限撤销、余额、库存和流程状态等关键判断,不应只凭可能陈旧的副本完成最终授权或扣减。允许旧值的内容展示则可以使用副本,但要避免同一页面中相互依赖的查询来自不同时间点,导致合计数和明细对不上。

  • 为每个关键接口记录读主、读副本或带位置等待的理由。
  • 明确延迟超限时回主库、返回处理中、展示截止时间或拒绝请求。
03

复制延迟要拆成发送、接收、写入与回放

一个“延迟秒数”可能掩盖不同问题。监控至少要能判断主库产生的日志是否发送、副本是否接收并持久化、是否已经回放为查询可见状态,以及各阶段剩余多少数据;只有回放完成,新的只读快照才可能看到该事务。

PostgreSQL 官方文档说明热备数据到达与回放需要时间,同一查询在主库和副本上可能返回不同结果;同步复制的确认点也不同。等待副本收到或写入日志,不一定等于查询已经可见,`remote_apply` 才是等待同步副本回放提交的一种配置语义。不同数据库和托管服务应核对自己的确认位置,不能把产品名中的“同步”直接解释为所有读取实时一致。

延迟告警同时记录时间与积压字节更容易解释:低写入时位置差很小但最后回放时间较旧,高写入时很短时间也可能积压大量日志。还要关联网络、磁盘、回放进程、长事务和副本查询,避免只重启副本而不处理持续原因。

  • 按实例监控连接、接收、持久化、回放位置和延迟趋势。
  • 为路由设置比业务新鲜度预算更早的摘除与恢复条件。
04

副本查询要受资源和回放冲突约束

把报表与列表移到副本后,查询仍会消耗 CPU、内存、磁盘和临时空间。长查询可能与日志回放需要清理或修改的对象冲突;系统可能选择等待回放而增加延迟,也可能取消查询以继续追赶主库。

PostgreSQL 热备官方资料列出 DDL 锁、清理旧行版本等回放冲突,并说明超过配置的等待后可取消查询。放宽等待能够让报表继续,却会让副本更久看不到主库新变化;启用反馈减少部分清理冲突,又可能让主库旧行无法及时清理并产生膨胀。这些都是业务取舍,不是一个参数同时解决。

把交互查询和大报表区分资源预算。导出任务设置并发、超时、扫描范围和数据截止点,必要时使用独立分析副本或离线数仓;不要让用于故障提升的高可用副本长期被不可控报表拖住。副本恢复追赶时也应限制查询流量,先确认回放进入安全范围。

  • 统计副本查询取消、临时文件、I/O、CPU 和回放等待原因。
  • 高可用副本与分析副本若共用,明确故障时谁优先以及怎样限流。
05

实施步骤:小范围分流,再逐类扩大

先建立主库与副本基线,选择允许短暂陈旧且容易验证的一条查询路径,加入角色明确的连接池与路由标记;随后增加延迟门控、写后读策略、超限回退和观测,再逐类迁移其他读取。

应用必须区分只读连接和读写连接,事务内不能在两个连接之间随意漂移。对“看似 SELECT、实际需要锁或写入”的语句单独检查;PostgreSQL 热备禁止 DML、DDL、序列更新以及需要行锁的 `SELECT ... FOR UPDATE` 等操作。ORM、会话初始化和临时表也可能让原本计划的副本查询失败。

每次扩大前比较主库读取下降、副本资源、复制延迟、业务错误和总连接数。读副本增加了连接池时,要控制所有应用实例到主库与各副本的连接上限,避免为了分流反而耗尽数据库连接。变更使用可回退配置灰度,不在同一窗口同时大改索引、路由和复制拓扑。

  • 从一个容忍陈旧的只读接口灰度,保留稳定的强制读主开关。
  • 为事务、后台任务、AI 智能体和小程序接口分别检查路由上下文。
06

验收:把延迟、断连、长查询和主库故障一起演练

验收需覆盖正常读写、持续写入、写后立即查询、副本暂停与追赶、长报表、连接断开、主库切换和旧主库重新接入。除了吞吐和延迟,还要核对订单、权限、库存及报表截止时间是否符合约定。

故障提升不能只证明新主库可连接。应确认应用发现并切换写入目标、旧主库被隔离、连接池不再复用旧地址、尚未复制的事务如何识别,以及原主库恢复后以什么角色重新加入。异步复制在主库灾难故障时可能缺少尚未传送或回放的提交,风险必须与业务恢复点一起说明。

压测固定数据规模、读写比例、热点分布和查询集合,对比分流前后的主库有效容量,而不是只看副本 QPS。恢复阶段检查路由何时重新纳入副本,避免刚连接就承接全部读取再次落后。最终报告保存拓扑、版本、路由规则、延迟预算、故障时间线和无法覆盖的托管服务行为。

  • 验证写后读、跨页面连续查询和关键授权不会因副本落后出错。
  • 证明副本超限时的摘除、回退与恢复不会把主库突然压垮。

需求讨论中的问题

有了只读副本,所有查询都可以自动分过去吗?

不可以。写后立即确认、权限撤销、库存与余额判断等路径可能需要权威新状态;事务内查询、行锁、临时表或隐含写入也可能不能在只读副本执行。应按业务语义逐类分流。

使用同步复制后,副本读取就一定没有延迟吗?

取决于数据库和确认点。确认副本收到或持久化日志,不一定表示已经回放并对查询可见;等待回放又会增加提交等待并受副本可用性影响。必须按具体产品配置和业务目标验证。

副本延迟时统一回主库是不是最安全?

对业务正确性可能更稳,但大量查询同时回流会形成新的主库峰值。需要分业务优先级、限制回流速率,并为可陈旧展示、处理中状态和受控拒绝预先定义行为。

只读副本能同时替代备份和容灾吗?

不能直接替代。错误操作通常会复制过去,异步故障提升还可能缺少未到达的事务。备份恢复、故障提升和查询分流应分别定义目标、演练和证据。

带走这份清单

读写分离上线验收清单

可逐项勾选,辅助本次阅读;刷新页面后不保留。

参考资料

技术概念可进一步阅读以下资料;文中的业务场景与实施清单用于方案讨论。

  1. PostgreSQL:Log-Shipping Standby Servers

    核验流复制、异步数据丢失窗口,以及同步确认到写入或回放阶段的不同语义。

  2. PostgreSQL:Hot Standby

    核验副本读取的最终一致性、只读限制、查询与 WAL 回放冲突及相关运行取舍。

  3. PostgreSQL:Monitoring Database Activity

    核验复制发送与接收状态、日志位置及数据库冲突等可观察入口;实际指标按使用版本确认。

#读写分离#复制延迟#数据一致性#故障切换
从阅读,到行动

需要评估现有系统的性能瓶颈?

提供关键业务路径、真实峰值、服务器与数据库配置,以及现有压测或故障记录,月弦科技可据此梳理优化顺序、实施范围和可验证的验收条件。