附录 · 何时该升级架构:量化触发信号
08 章 说过:别凭「感觉旧了/丑了」或「大厂都上了」就升级架构,要看「某个你在乎的质量属性,是不是被真实瓶颈卡住了」。 这份速查,把那句话落成可观测的量化信号——当你看到这些信号,才是该动手的时候。
⚠️ 重要:下面的数字是「经验数量级」,不是铁律。 真实阈值取决于你的硬件、数据形态、业务容忍度。把它们当「该警惕了」的提示,而不是「到这个数就必须改」的命令。真正的依据永远是:某个质量属性被真实瓶颈卡住(且你量出来了)。
读 / 写 / 存储:数据层的信号
| 你观测到的信号(经验区间) | 大概率的瓶颈 | 常见破解(见 05) |
|---|---|---|
| 主库 CPU 持续 > 70%、读请求排队 | 读打满了 | 加读副本(复制扩读)+ 缓存 |
| 缓存命中率掉到 < 90%、回源压力大 | 缓存不够 / 失效策略差 | 调缓存粒度、TTL、预热;防穿透击穿雪崩 |
| 单表行数过千万 ~ 上亿,或单库容量过几百 GB | 单库装不下 / 写变慢 | 考虑分片(扩写),但要慎选分片键 |
| 写 QPS 接近单库上限、主库成为写瓶颈 | 写打满了(复制救不了) | 分片;或拆出独立写服务 |
| 同一份数据被多种查询形态折磨(又要事务又要全文又要聚合) | 一种存储扛了不该扛的活 | 按访问形态拆存储(多语言持久化) |
延迟 / 性能:体验层的信号
| 信号 | 瓶颈 | 破解 |
|---|---|---|
| P99 延迟持续超标(而 P50 还好) | 尾延迟——某条慢路径 / 资源争抢 | 找最慢那一跳针对性优化,别动 P50 |
| 某个耗时操作让用户干等 > 几秒 | 同步阻塞了不该同步的活 | 异步化 + 队列削峰(04) |
| 流量出现规律性尖峰(开售/大促/早晚高峰) | 按峰值堆机器太贵、按均值又被冲垮 | 削峰填谷 + 弹性扩缩 + (极端)排队 |
可用性 / 可靠性:稳定性的信号
| 信号 | 瓶颈 | 破解 |
|---|---|---|
| 业务要求可用性上一个台阶(99% → 99.9% → 99.99%) | 单点 / 无冗余撑不住更高的 9 | 消灭单点、加冗余、故障域隔离、多活 |
| 某组件一挂全系统瘫(SPOF) | 存在单点故障 | 冗余 + 自动故障转移 |
| 一次故障波及面过大、恢复慢 | 故障域没隔离 | 隔离爆炸半径、限流降级、熔断 |
组织 / 研发效率:最容易被忽视的信号
| 信号 | 瓶颈 | 破解(注意:常是组织问题) |
|---|---|---|
| 改一处牵动一片、发布越来越慢、谁都不敢动 | 模块边界烂 / 耦合过紧 | 先理清模块边界(模块化单体);未必要拆服务 |
| 多团队在一个代码库里互相阻塞、上线排队 | 「人」的扩展性到顶了 | 这才是微服务的真正信号——但先看团队边界(康威定律,见 08) |
| 新人上手要好几周、改个功能要动很多地方 | 可维护性差 | 重构边界、补文档/ADR,而非堆新功能 |
怎么用这张表
- 先量,再判断。 没有监控数据(QPS、P99、命中率、CPU、容量)就谈升级,都是拍脑袋。先把这些指标盯起来。
- 一次只解一个瓶颈。 升级架构有巨大成本和风险,它必须是为了换取某个当下被卡住的质量属性——别一次重构全家桶。
- 每次升级都写一条 ADR:什么信号触发了它、升成什么、放弃了什么。
- 没触发,就别动。 没有信号还要升级,十有八九是过度设计或跟风——记住 09 章:个人/小团队的默认审美是「克制」。
一句话:架构升级是「被真实信号触发的、有据可查的决策」,不是「定期重构的仪式」,也不是「追新的冲动」。