弹力设计最重要的观念是:故障不是例外,而是系统需求的一部分。
很多系统设计在文档里默认一切正常:网络、依赖、数据库、队列、用户行为。但真实世界刚好相反——依赖会超时,消息会重复,数据会短暂不一致,流量会突然升高,人也会误操作。
如果设计没有承认这些事实,故障就会在生产环境替你补课。
Design for Failure
把故障处理当成功能写入代码,是弹力设计的核心。
这意味着系统不只要有主流程,还要显式定义失败后的行为:
- 请求重复时会不会产生重复副作用?
- 部分步骤成功、部分步骤失败时如何补偿?
- 下游持续失败时是否继续重试?
- 流量超过能力边界时保护谁、牺牲谁?
- 数据短暂不一致时用户看到什么?
- 故障恢复后如何重新对账和收敛?
这些问题如果不上设计桌,最后就会上事故复盘——选一个吧。
幂等性:先控制副作用
幂等性的重点不是每次返回结果都一样,而是一次执行与多次执行造成的副作用一致。
在分布式系统里,重复几乎不可避免:客户端会重试,网关会重试,消息队列会重投,人也可能重复点击。没有幂等性,重试机制会从保护手段变成放大器。
常见设计手段包括:
- 请求唯一 ID。
- 业务幂等键。
- 状态机流转约束。
- 去重表或去重缓存。
- 操作前检查当前状态。
- 对外接口明确幂等语义。
幂等性不是某个接口的装饰,而是业务流程能否安全重试的基础。
补偿事务:承认一致性有成本
单机数据库事务可以依赖 ACID,但跨服务、跨数据库、跨系统的业务流程很难保持同样的强一致体验。很多时候,系统需要在性能、可用性和一致性之间做取舍。
补偿事务的思路是:先努力把流程向前推进;如果推进不下去,就启动补偿动作,让业务回到可接受状态。
它要求设计者显式定义:
- 每一步的正向动作。
- 每一步失败后的补偿动作。
- 哪些步骤可重试,哪些不可重试。
- 补偿失败时如何人工介入。
- 如何记录状态,避免流程卡死在中间。
补偿不是事后补丁,而是流程设计的一部分。
熔断和限流:保护系统边界
当下游错误很多、长时间不可恢复,继续重试通常没有意义。熔断的价值在于及时停止无效请求,保护后端不被过载拖垮,也让调用方尽快走降级路径。
限流则是在系统入口或关键资源前设置边界。流量暴增时,系统必须回答一个现实问题:资源不够时优先保障什么?
几类策略很常见:
- 拒绝超出能力范围的请求。
- 对非核心功能降级。
- 给关键用户或关键业务保留资源。
- 用队列延迟处理短时峰值。
- 对可水平扩展的服务做弹性伸缩。
限流不是简单地“挡请求”,而是把系统能力边界产品化、策略化。
弹力设计是工程成熟度
初级系统追求功能可用,成熟系统追求失败可控。
一个系统有没有弹力,不是看平时有多快,而是看故障时是否能保持边界:核心功能是否可用,数据是否可恢复,用户是否有明确反馈,工程团队是否知道下一步做什么。
这也是《左耳听风》弹力设计部分最值得记住的地方:真正的工程能力,不是让故障永不发生,而是让故障发生时,系统仍然有秩序。
资料来源
raw/zuoear-41丨弹力设计篇之认识故障和弹力设计-highlights.mdraw/zuoear-44丨弹力设计篇之幂等性设计-highlights.mdraw/zuoear-46丨弹力设计篇之补偿事务-highlights.mdraw/zuoear-48丨弹力设计篇之熔断设计-highlights.mdraw/zuoear-49丨弹力设计篇之限流设计-highlights.md
如果这篇文章对你有帮助,欢迎分享给更多人!
部分信息可能已经过时






