Skip to content

案例串讲:读多、写多、低延迟、强一致四条主线

本文是系统设计系统学习的 L3 实战篇。前置:31. high-performance-patterns32. high-availability-patterns。 本系列 27 个案例的全景总串讲,读完可以对 27 篇的归属和套路一览无余。

为什么需要这根主线

27 个分布式系统案例,表面看各有各的解法:短链用哈希、Feed 用推拉结合、秒杀用削峰、IM 用长连接……但仔细看,它们的核心矛盾只有四种:

  • 读多写少:瓶颈在缓存
  • 写多:瓶颈在写路径
  • 低延迟:瓶颈在网络和状态
  • 强一致:瓶颈在协调

一个系统设计有没有"章法",就看你能不能把新需求快速对号入座到某条主线,复用该主线的成熟套路。

案例归类地图

主线流量特征核心瓶颈对应案例编号
读多写少读:写 ≥ 10:1缓存命中率 + 回源压力01/03/10/11/14/13/24
写多写 QPS > 10k/s写入吞吐 + 持久化02/06/07/12/15/25
低延迟P99 ≤ 200ms传输路径 + 状态外置04/05/08/16/23/27
强一致读写涉及金钱/库存锁 + 事务 + 协调09/17/18/19/20/21/22/26

27 篇全部可以归入这四条线,没有例外。

读多写少线:多级缓存 + 预热 + 兜底

代表案例:短链服务(01)、Feed 流(03)、排行榜(11)、CDN 设计(23)、推荐系统(24)

读多写少的系统,核心战术是"把数据放到离用户最近的地方"。

多级缓存的漏斗层级:

用户请求 -> 浏览器缓存 -> CDN -> 网关缓存 -> 本地缓存 -> Redis -> DB

每一层拦截一部分流量。设计时只需要回答三个问题:

  1. 每层拦多少?——短链的 302 重定向中,CDN 拦掉 80% 的请求,回源请求只有 20%
  2. 缓存什么?——Feed 流里,用户的 timeline 列表缓存在 Redis,但具体每条内容从 DB 读(混合存储)
  3. 缓存满了怎么办?——LRU 淘汰 + 异步预热(排行榜的定时重算)

常见陷阱:缓存穿透(大量不存在的 key 绕过缓存打 DB)——短链的 hash 冲突用布隆过滤器拦住;缓存雪崩(大量 key 同时过期)——过期时间加随机偏移。

写多线:削峰 + 批量 + 异步落库

代表案例:秒杀(02)、日志收集(12)、支付(15)、实时管道(25)

写多的系统,核心矛盾是"瞬间峰值远超平均"。系统按平均 QPS 建,但峰值可能 10 倍。

削峰三板斧:

请求 -> 限流(拦掉超量) -> MQ 削峰(排队) -> 批量刷盘(写合并) -> DB

秒杀案例的典型数字:限流前 100w QPS,限流后 1w 放行,MQ 以 5000/s 的速度消费,DB 批量插入 5000/s。用户收到"排队中"的反馈,不需要实时知道结果——这就是"异步化"。

支付场景更严格:不能丢也不能重。幂等表 + 事务消息 + 对账兜底是标准组合。支付系统不会只靠 DB 事务保证,一定有一个离线对账程序,每天跑一遍"交易对不上的单子"。

低延迟线:长连接 + 地理分片 + 就近接入

代表案例:网约车(04/27)、IM(05)、配置中心(08)、通知系统(16)

低延迟系统,P99 比平均 QPS 更重要。用户能接受 1% 的请求挂掉,但不能接受 1% 的请求卡 5 秒。

IM 的架构骨架:WebSocket 长连接(避免 TCP 三次握手开销) -> 连接管理器(路由表) -> 消息分片(按用户 ID 哈希) -> 持久化与推拉结合。

网约车的难点在不同子问题有不同的延迟要求:

  • 乘客下单:写多线,接受 1-2 秒
  • 司机接单推送:低延迟线,P99 < 500ms
  • 轨迹上传:写多线,接受 5 秒
  • ETA 查询:读多写少线,P99 < 200ms

同一个系统,不同子模块走不同主线。这不是混合,这是按功能分治

强一致线:幂等 + 事务消息 + 对账

代表案例:分布式锁(09)、权限系统(17)、数据隐私(18)、多活(19)、KV 存储(21)、对象存储(22)、分布式文件系统(26)

强一致的核心矛盾是"分布式环境下,两个节点没法同时看到最新的全局状态"。CAP 定理把这个矛盾说透了,但 CAP 是分析工具,不是设计工具。

支付系统的实际做法

扣款请求 -> 本地事务写扣款记录 -> 发事务消息 -> 下游消费 -> 幂等去重

不是"分布式事务 XA",而是"本地事务 + 可靠消息 + 幂等消费"。最终一致 + 对账兜底,比强一致分布式事务更可靠,也更简单

对账才是真正的"最终一致性警察"。支付系统每天凌晨跑一次对账脚本,把"本系统认为成功"的单子和"外部认为成功"的单子逐条对比,不一致的走人工处理。没有任何分布式事务协议能覆盖这个场景。

实战:迁移学习法

拿到一道新系统设计题,拆解步骤:

  1. 归类:读多写少?写多?低延迟?强一致?还是混合(如网约车有多个子问题)
  2. 套骨架:走对应主线的基础架构模板
  3. 加差异:这个系统的特殊约束是什么?数据量级?一致性要求?读写比例?
  4. 深挖瓶颈:按四步分析法(28 篇)的估算,找出哪个组件会先挂

新题套用模板

需求澄清:用户规模、读写比、一致性、延迟
主线判断:____
估算:QPS ____、存储 ____、带宽 ____
架构骨架:[对应主线的标准架构图]
差异点:[特殊约束对应的定制化方案]
瓶颈分析:哪个组件先扛不住,怎么优化

举例:设计一个"在线文档协作系统"。

  • 读多写少(大部分时间用户只看文档) + 低延迟(编辑时要实时同步)
  • 读多线骨架:CDN 加速静态内容 + 缓存文档元数据
  • 低延迟线骨架:WebSocket + 操作转换(OT/CRDT)
  • 差异点:多人同时编辑的冲突解决,比 IM 的简单消息传递复杂得多
  • 瓶颈:写冲突的合并效率,不是缓存

迁移学习法的核心不是背模板,而是知道"这个新问题跟哪个老问题最像,哪里不一样"

常见误区与小结

  • 误区 1:以为缓存能解决所有问题。缓存只解决读多写少,写多场景缓存会拖后腿
  • 误区 2:所有系统都想要强一致。92% 的互联网业务最终一致就够,引入强一致方案的成本是 3-5 倍开发量
  • 误区 3:秒杀系统和支付系统都用 MQ 削峰,但支付对 MQ 的可靠性要求高一个量级
  • 误区 4:低延迟只靠网络优化。更常见的是减少不必要的 RTT(合并请求、批量处理)
  • 误区 5:对账是"最后手段",实际上它应该从第一天就设计到系统里

小结:系统设计没有银弹。四条主线 + 迁移学习法,让你面对任何新题都能快速定位到"这条线用什么套路"。"读多看缓存、写多削峰、低延迟近端、强一致对账"——记住这四句话,再难的系统也能拆出骨架。

本系列 27 个案例的完整索引:01-短链服务02-秒杀03-Feed 流04-网约车05-IM06-ID 生成器07-限流系统08-配置中心09-分布式锁10-ES11-排行榜12-日志收集13-评论系统14-直播15-支付16-通知17-权限18-数据隐私19-多活20-取舍21-Dynamo22-S323-CDN24-推荐25-实时管道26-HDFS27-网约车调度

参考

参考:本系列 28-32 篇(system-design 学习篇)的全部内容,以及 01-27 篇案例

手撕 → 框架 → 生产化,一步步把 AI Agent 工程化搞透。
粤ICP备2026104257号-1