mobile wallpaper 1mobile wallpaper 2mobile wallpaper 3mobile wallpaper 4
1146 字
3 分钟
弹力设计:把故障当成系统需求
2026-05-23

弹力设计最重要的观念是:故障不是例外,而是系统需求的一部分。

很多系统设计在文档里默认一切正常:网络、依赖、数据库、队列、用户行为。但真实世界刚好相反——依赖会超时,消息会重复,数据会短暂不一致,流量会突然升高,人也会误操作。

如果设计没有承认这些事实,故障就会在生产环境替你补课。

Design for Failure#

把故障处理当成功能写入代码,是弹力设计的核心。

这意味着系统不只要有主流程,还要显式定义失败后的行为:

  • 请求重复时会不会产生重复副作用?
  • 部分步骤成功、部分步骤失败时如何补偿?
  • 下游持续失败时是否继续重试?
  • 流量超过能力边界时保护谁、牺牲谁?
  • 数据短暂不一致时用户看到什么?
  • 故障恢复后如何重新对账和收敛?

这些问题如果不上设计桌,最后就会上事故复盘——选一个吧。

幂等性:先控制副作用#

幂等性的重点不是每次返回结果都一样,而是一次执行与多次执行造成的副作用一致。

在分布式系统里,重复几乎不可避免:客户端会重试,网关会重试,消息队列会重投,人也可能重复点击。没有幂等性,重试机制会从保护手段变成放大器。

常见设计手段包括:

  • 请求唯一 ID。
  • 业务幂等键。
  • 状态机流转约束。
  • 去重表或去重缓存。
  • 操作前检查当前状态。
  • 对外接口明确幂等语义。

幂等性不是某个接口的装饰,而是业务流程能否安全重试的基础。

补偿事务:承认一致性有成本#

单机数据库事务可以依赖 ACID,但跨服务、跨数据库、跨系统的业务流程很难保持同样的强一致体验。很多时候,系统需要在性能、可用性和一致性之间做取舍。

补偿事务的思路是:先努力把流程向前推进;如果推进不下去,就启动补偿动作,让业务回到可接受状态。

它要求设计者显式定义:

  • 每一步的正向动作。
  • 每一步失败后的补偿动作。
  • 哪些步骤可重试,哪些不可重试。
  • 补偿失败时如何人工介入。
  • 如何记录状态,避免流程卡死在中间。

补偿不是事后补丁,而是流程设计的一部分。

熔断和限流:保护系统边界#

当下游错误很多、长时间不可恢复,继续重试通常没有意义。熔断的价值在于及时停止无效请求,保护后端不被过载拖垮,也让调用方尽快走降级路径。

限流则是在系统入口或关键资源前设置边界。流量暴增时,系统必须回答一个现实问题:资源不够时优先保障什么?

几类策略很常见:

  • 拒绝超出能力范围的请求。
  • 对非核心功能降级。
  • 给关键用户或关键业务保留资源。
  • 用队列延迟处理短时峰值。
  • 对可水平扩展的服务做弹性伸缩。

限流不是简单地“挡请求”,而是把系统能力边界产品化、策略化。

弹力设计是工程成熟度#

初级系统追求功能可用,成熟系统追求失败可控。

一个系统有没有弹力,不是看平时有多快,而是看故障时是否能保持边界:核心功能是否可用,数据是否可恢复,用户是否有明确反馈,工程团队是否知道下一步做什么。

这也是《左耳听风》弹力设计部分最值得记住的地方:真正的工程能力,不是让故障永不发生,而是让故障发生时,系统仍然有秩序。

资料来源#

  • raw/zuoear-41丨弹力设计篇之认识故障和弹力设计-highlights.md
  • raw/zuoear-44丨弹力设计篇之幂等性设计-highlights.md
  • raw/zuoear-46丨弹力设计篇之补偿事务-highlights.md
  • raw/zuoear-48丨弹力设计篇之熔断设计-highlights.md
  • raw/zuoear-49丨弹力设计篇之限流设计-highlights.md
分享

如果这篇文章对你有帮助,欢迎分享给更多人!

弹力设计:把故障当成系统需求
https://example.com/posts/05-zuoear-resilience-design/
作者
QWL
发布于
2026-05-23
许可协议
CC BY-NC-SA 4.0

部分信息可能已经过时

目录