《后端架构设计·高性能与高可用》目录与学习路径

《后端架构设计·高性能与高可用》的阅读入口:13 章分四段的结构、章节依赖图、三条阅读路径、症状到章节的对照表、arch-lab 在卷二新增的度量与治理组件与代码分级、实测值与目标值的口径,以及从延迟预算、容量估算到高可用改造和故障演练的完整链路。

本卷要解决的问题

卷二不教 Go 语法,也不教怎么装 Prometheus。它只回答一个问题:当系统已经有了边界,下一步怎样让它在流量、故障和变更下仍然“快得住、扛得住、退得回”。

具体拆成四件事:

  1. 把“快”从感觉变成读数:吞吐、延迟、尾部延迟和性能预算;
  2. 把“容量”从拍脑袋变成算式:业务指标 → QPS → 并发 → 实例数;
  3. 把过载和故障限制在局部:缓存、异步、池化、限流、熔断、重试、超时;
  4. 让变更可控地发生:冗余、切换、健康检查、发布、回滚、观测和复盘。

卷一解决“边界画在哪”,卷二解决“边界内的代价怎么付”,卷三处理分布式与一致性,卷四处理演进与治理。卷二会反复提到卷一的结构,但不重复定义限界上下文、端口适配器和数据所有权。

全书结构:13 章分四段

段落章节回答的问题本段产出
一、度量与容量第 1–2 章慢在哪里?能扛多少?延迟直方图、性能预算表、容量算式、压测报告
二、单机与链路治理第 3–7 章怎样把过载挡在局部?多级缓存、异步链路、连接池、舱壁、限流、熔断、重试与超时
三、拓扑与变更第 8–10 章坏了怎么切?变更怎么退?故障域图、主备切换流程、健康检查、发布与回滚方案
四、数据与收口第 11–13 章数据库这一层怎么提速?整套改造怎么验收?索引与分页优化、读写分离预算、容量规划、故障场景清单

13 章不是 13 个性能技巧的堆叠。每一章都往 arch-lab 里加一层可运行或可检查的产物,第 12 章把这些产物合成一次完整的改造,第 13 章给出验收口径和进入卷三的交接。

章节依赖图

第 1 章 度量(吞吐 / 延迟 / 预算)
   │
   └──► 第 2 章 容量(QPS / 压测 / 余量)
            │
            ├──► 第 3 章 缓存(本地 / 分布式 / 一致性)
            │        │
            │        └──► 第 11 章 数据层(索引 / 分页 / 读写分离)
            │
            ├──► 第 4 章 异步(收益 / 语义 / 积压)
            │
            ├──► 第 5 章 资源池(连接 / 线程 / 舱壁)
            │
            └──► 第 6–7 章 过载治理(限流 / 熔断 / 重试 / 超时 / 幂等)
                     │
                     ├──► 第 8 章 拓扑(冗余 / 切换 / 摘流)
                     │
                     ├──► 第 9 章 发布(滚动 / 回滚 / 开关)
                     │
                     └──► 第 10 章 观测(契约 / 告警 / 复盘)
                              │
                              └──► 第 12 章 贯穿项目(改造前后)
                                       │
                                       └──► 第 13 章 综合(容量 / 故障 / 交接)

这张图表达“先有什么再有什么”的阅读顺序,不是代码依赖。第 5、6、7 章可以互换;第 12 章必须放在第 3、4、6 章之后,因为它要把缓存、异步和限流装进同一条链路;第 13 章需要第 2、8、9 章的结论。

十三章速览

第 1 章 性能问题的定义与度量

先把“快”拆成吞吐、平均延迟、尾部延迟三个不同的问题,再讲怎么从 CPU、内存、I/O、锁四类瓶颈里定位真正的时间去处,最后把端到端目标拆成每个调用的绝对截止时间。

产出:延迟直方图与分位数、瓶颈判定表、下单链路 400ms 预算表。

第 2 章 容量估算与压测

从业务指标(日订单、峰值系数、读写比)推 QPS 和并发数,再讨论压测模型、数据构造和流量回放,最后讲怎么读结果、留多少容量余量。

产出:容量算式、开环/闭环压测器、一份带置信边界的压测结论。

第 3 章 缓存体系

比较本地缓存、分布式缓存和多级缓存的命中率与一致性代价,处理失效、更新和并发回源,最后给出穿透、击穿、雪崩和热 key 的治理组合。

产出:多级缓存实现、singleflight、逻辑过期、热 key 探测。

第 4 章 异步化与消息

算清同步改异步的收益与代价,区分 at-most-once、at-least-once 和 effectively-once 的责任边界,再处理积压、顺序、死信和定时对账。

产出:异步改造判据、消费幂等表、积压与死信处置流程。

第 5 章 资源池与隔离

从连接池、线程池和协程池的容量与排队讲起,再用信号量舱壁和资源配额隔离不同调用方,最后分析慢调用怎样沿调用链扩散。

产出:池参数计算、舱壁实现、慢调用传播的失败注入结果。

第 6 章 限流与熔断

比较令牌桶、漏桶、滑动窗口和分布式租约,再实现三态熔断状态机与半开恢复,最后讨论降级、兜底和用户可感知的体验。

产出:限流器、租约式分布式限流、熔断状态机、降级决策表。

第 7 章 超时、重试与幂等

把超时预算沿调用链传下去,算清重试放大与退避抖动,最后用幂等键和去重窗口保证重复请求不产生重复副作用。

产出:截止时间传播、带抖动的重试策略、幂等键存储与故障注入测试。

第 8 章 高可用拓扑

从冗余、故障域和单点消除讲到单区域主备切换,再处理健康检查、流量摘除和在途请求。

产出:故障域图、主备切换流程、健康检查状态机、摘流脚本。

第 9 章 发布与可用性

比较滚动、蓝绿和金丝雀的代价,处理回滚、兼容窗口和数据迁移,最后讨论开关与灰度对数据兼容的约束。

产出:发布策略选择表、兼容窗口检查、开关与数据迁移的先后顺序。

第 10 章 观测与告警

定义订单链路的最小观测契约,把告警从“指标超阈值”改成“症状到行动”的闭环,最后用复盘把一次故障变成可验证的改进项。

产出:trace/日志/指标契约、告警规则、复盘模板与改进台账。

第 11 章 数据层性能

从索引、查询和慢 SQL 讲到分页、批处理与连接管理,再讨论读写分离的延迟预算和一致性兜底。

产出:索引设计、深分页改写、连接池参数、读写分离延迟预算。

第 12 章 贯穿项目:交易系统的高并发改造

把前十一章的机制装进同一个订单系统:先测基线、找瓶颈,再做缓存、异步和限流改造,最后用同一口径比较改造前后,并注入失败验证降级路径。

产出:基线报告、改造清单、改造前后对照数据、失败注入结果。

第 13 章 卷二综合

完成一次从业务目标到实例数的容量规划,列出订单系统必须测的三个故障场景,最后把未解决的问题交接给卷三。

产出:容量规划表、故障场景清单、卷三问题清单。

三条阅读路径

路径 A:顺序通读

适合第一次系统补性能与高可用知识、准备架构评审或面试的读者。

阶段章节建议投入读完应该能做什么
建立度量第 1–2 章5–6 小时设计延迟指标、做一次可信压测、算出容量
治理单机第 3–5 章8–10 小时设计缓存、异步链路和资源池
治理过载第 6–7 章6–8 小时配置限流、熔断、重试、超时和幂等
拓扑与变更第 8–10 章8–10 小时设计切换、发布、回滚和告警
数据与验收第 11–13 章8–10 小时优化数据层、完成改造对照和故障清单

总计约 35–44 小时。代码量比卷一多,建议至少完整跑通第 3、6、7 章的 L1 测试,否则很容易把“看起来对”当成“跑得通”。

路径 B:改造驱动

适合手上正有一个慢系统或一次高并发改造任务的读者。

按这个顺序读:

  1. 1.2 瓶颈定位
  2. 2.1 从业务指标到 QPS
  3. 12.1 压测基线与瓶颈分析
  4. 3.1 多级缓存 与 4.1 同步改异步
  5. 6.1 限流 与 6.2 熔断
  6. 12.3 改造前后的数字
  7. 用附录 C 故障演练检查表 做一次演练

这条路径不要求读完前两章的所有细节,但第 1 步和第 3 步不能跳:没有基线,后面的“优化了多少”都无法回答。

路径 C:问题驱动

适合线上已经有具体症状的读者。先查表,再跳章。

症状先读再读
平均延迟正常,用户仍抱怨慢1.1 尾部延迟1.3 性能预算
不知道能扛多少流量2.1 QPS 与并发2.3 容量余量
缓存越加越不一致3.2 缓存一致性3.3 穿透与热 key
消息积压、重复消费4.2 投递语义4.3 积压与死信
一个慢接口拖垮整个服务5.3 慢调用扩散5.2 舱壁隔离
峰值被打穿、限流不准6.1 限流算法6.3 降级与兜底
重试把下游打挂7.2 重试放大7.1 超时预算
重复下单、重复扣款7.3 幂等键4.2 消费幂等
单点故障、切换不敢做8.1 故障域8.2 主备切换
发布就出事、回滚不干净9.2 回滚与兼容窗口9.3 开关与数据兼容
告警太多、真故障没人管10.2 告警闭环10.3 复盘闭环
慢查询、深分页、连接打满11.1 索引与慢 SQL11.2 分页与连接

arch-lab 在卷二扩展了什么

卷二沿用卷一的订单系统:Order、InventoryReservation、Payment 三个聚合,CREATED → INVENTORY_RESERVED → PAID → FULFILLED 状态机,以及同一组错误码。卷二不重画边界,只在边界内加四组能力。

组新增组件放在哪里
度量直方图、分位数、三本账internal/platform/metrics
容量开环/闭环压测器、容量计算器cmd/loadgen、internal/platform/capacity
治理缓存、限流、熔断、重试、舱壁、幂等internal/platform/*
运行时健康检查、摘流、发布分流、开关internal/platform/health、internal/platform/runtime

这些组件不改变领域层。订单聚合仍然不知道缓存和熔断的存在;平台能力通过端口和中间件接入,业务代码只感知“调用可能失败、可能超时、可能被拒绝”。

代码分四级,与卷一相同:L1 纯逻辑、L2 进程内端到端、L3 真实依赖、L4 多节点与故障注入。卷二的大部分章节是 L1;第 8、10、12、13 章至少各有一个 L2 场景;L3 只承诺实际启动过 PostgreSQL 或 Redis 的部分;L4 只在第 13 章讨论场景,不承诺完整实验。

数字口径:实测、目标与示例

性能书最容易骗人的地方是数字。卷二统一用三种口径:

类型写法用途
实测值附命令、环境、样本量,例如“本机 darwin/arm64,1000 次请求,P99=20ms”证明某次运行的结果
目标值写成 SLO 或预算,例如“下单 P99 目标 400ms”设计约束,不是测量结果
示例值用于公式或配置形状,例如“单实例按 50 请求/秒估算”说明计算过程

看到“实测”时,先看有没有命令和原始输出;没有的,按目标值或示例值理解。反过来,实测值也只代表当次机器和当次流量,不能直接外推成生产容量。第 2 章会专门讲怎么设计压测、怎么给结论加边界。

Java 对照只用于解释结构差异,例如虚拟线程与 goroutine 的调度模型、线程池队列与 Go channel 的背压方式。所有 Java 结论都用 JDK 21 实际运行,不用本机默认 JDK,也不引入 Spring 或 Maven。

每篇文章的结构

卷二 39 篇正文的结构基本一致。知道骨架,就能决定哪些段落细读、哪些段落跳过。

部分作用建议
开篇场景用一个具体问题或失败案例切入先判断是否与你的系统相似
机制与取舍解释为什么这样设计、代价是什么细读,别只看结论
代码与测试可抽取、可运行的最小实现至少跑一次 L1
arch-lab 落点该机制放在订单系统的哪一层对照卷一的结构
真实运行命令、输出与解读注意是开环还是闭环
常见错误与边界五条左右的失效模式上线前逐条自查
小结与导航收束本节并给下一节链接决定继续读还是回查

每篇都至少有一个可运行片段。代码块前的三行注释不是装饰:file 决定抽取路径,tier 决定验证级别,verify 给出应执行的命令。把这三行删掉再复制,抽取器会拒绝。

结尾的“常见错误与边界”通常比正文更接近生产。正文展示的是正确路径,这一节补的是限流器遇到时钟回拨、熔断器进入半开风暴、重试穿透预算之类的错误路径。跳过它,代码能跑,事故照样会来。

常用验证命令

书里的每段 Go 代码都可以抽取到临时模块单独编译。最小验证集合如下:

目的命令通过标准
格式gofmt -l .无输出
静态检查go vet ./...退出码 0
单元测试go test ./...全部 PASS
并发测试go test -race ./...无 DATA RACE
指定用例go test -run TestTokenBucket -v ./...输出与正文一致
压测器go run ./cmd/loadgen -rate 200 -duration 30s能正常结束并输出分位数
L3 数据库docker compose up -d && go test -tags=integration ./...只记录实际跑出的数字
Java 对照javac --release 21 ... && java -cp out app.Main先确认 java -version 是 21

抽取后的模块统一用 module archlab 和 go 1.26.0。如果 go vet 报路径错误,先检查代码块的 file 标记是否与正文一致,再检查是否把两个文件粘进了同一个代码块。

-race 不是可选项。第 3、5、6、7 章都有共享状态的并发组件,普通测试通过不代表没有数据竞争;-race 通过也不代表逻辑正确,但至少排除了最常见的错误来源。

版本与验证环境

组件版本用途
Go1.26.0全书主线代码
JavaTemurin 21.0.13虚拟线程与线程池对照
PostgreSQL18.4L3 索引、分页、连接池验证
Redis7.x(可选)分布式缓存与限流租约
操作系统macOS darwin/arm64本机测量环境

几条纪律:

  • Java 结论必须用 JDK 21 真跑,本机默认 JDK 8 不参与任何对照;
  • 没有启动过的数据库,正文写“预期行为”,不写“实测”;
  • 压测数字必须附并发模型、数据规模和运行次数;
  • 单次运行只代表当次环境,不包装成稳定结论;
  • 开环与闭环压测的结果不可直接比较,正文会注明用的是哪一种;
  • 容量结论必须给出余量,不把“压测跑通”等同于“生产能扛”。

六个常见误区

第一,把平均延迟当性能。平均值会被大量快请求拉低,真正影响用户的是 P95、P99 和超时率。第 1 章先用直方图把这件事说清楚。

第二,先加缓存再找瓶颈。缓存会掩盖问题,也会引入一致性和雪崩风险。顺序应该是先测基线、再定位、最后才决定加不加缓存。

第三,压测只看 QPS 不看延迟分布。系统在 5000 QPS 下“能返回”不等于“能可用”,要看尾部延迟是否已经越过 SLO。

第四,限流值拍脑袋。限流阈值应该来自容量和依赖承受能力,不是“线上大概这么多”。第 6 章会给计算方式,也会讲分布式限流的租约误差。

第五,重试当万能药。没有预算、没有退避、没有幂等的重试,会把一次抖动放大成雪崩。第 7 章把这三件事放在一起讲。

第六,故障演练只演“服务挂了”。真实故障更多是变慢、部分失败、依赖超时和流量倾斜。第 13 章列的三个场景都偏向这类“不彻底”的故障。

读完本卷的标准

不是“看完 45 篇”,而是能独立产出下面五样东西:

  1. 一张下单链路的延迟预算表,每个阶段有截止时间和降级项;
  2. 一份容量算式,从业务指标推到实例数,并说明余量;
  3. 一组可运行的治理组件:缓存、限流、熔断、重试至少各一个;
  4. 一次改造前后的同口径对照,附命令和失败注入结果;
  5. 一份故障场景清单,每个场景有观测信号、处置步骤和退出条件。

如果这五样能写出来,卷三的复制、共识和分布式事务才有讨论的基础。否则读得再多,也只是记住了一批中间件名词。

从哪开始

第一次读,从1.1 吞吐、延迟与尾部延迟 开始。手上有具体问题,直接用上面的症状表跳转。要做改造,先读12.1 压测基线与瓶颈分析 ,再回到对应章节。

全书完整篇目见书架 ,或按顺序从 1.1 走到 13.3。

继续阅读

探索更多技术文章

浏览归档,发现更多关于系统设计、工具链和工程实践的内容。

全部文章 返回首页

「books」更多文章

  1. 《互联网产品的 AI 架构·平台化与治理》附录 C 平台化评审清单
  2. 《互联网产品的 AI 架构·平台化与治理》附录 B 能力目录与配额字段速查
  3. 《互联网产品的 AI 架构·平台化与治理》附录 A 治理角色与职责速查