分布式系统

重试不是再发一次:幂等契约要覆盖写入与副作用

从超时后的不确定结果出发,设计幂等键、请求摘要、结果缓存与副作用去重,让客户端安全重试而不重复通知或扣配额。

好的实现不会依赖用户反复刷新碰运气,而会让每个阶段有明确输入、输出、超时和终态。 超时表示调用方不知道结果,不等于服务端没有执行。幂等记录必须与业务写入处于同一原子边界,并绑定主体和规范化请求摘要。

分布式正确性来自幂等键、租约、单调版本和可对账事实,而不是假设请求只到一次。超时代表结果未知,调用方不能未经确认就把它解释成失败。

先定义系统契约

这项能力横跨客户端、网络与服务端,局部最优很容易制造全局故障。工程决策需要同时约束两端行为、持久化事实和运维预算。

  • 首次请求占用键并持久化 pending;事务提交结果后保存状态码和响应摘要,重复键若 payload 不同返回冲突而非复用。
  • 为状态写出唯一所有者、版本号和终态;任何回调只能修改自己创建的版本。
  • 兼容性通过显式能力协商决定,旧客户端得到可解释的降级路径,而不是进入半可用状态。

“重试不是再发一次:幂等契约要覆盖写入与副作用”的交付标准是正常路径可用、异常路径收敛、资源有界,并且用户能理解系统为何采用当前状态。 这样得到的不是演示代码,而是能解释、能降级、能回滚的生产能力。

哪些情况会破坏契约

失败路径需要与成功路径共享同一套状态模型。只弹一个错误提示却不释放资源、不传播终态,下一次恢复就会继承脏状态。

  • 业务写入成功但幂等记录稍后写入会留下重复窗口;缓存 200 响应却不缓存确定性 4xx 会让客户端反复执行校验副作用。
  • 只修正界面状态而没有清理底层资源,下一次操作继承队列、锁或过期凭据并再次失败。
  • 降级路径从未压测,主路径故障时所有流量同时进入更慢、更昂贵的后备方案。

如何逐条验证契约

测试不能以“最后成功了”结束。还要测量经历了多少次副作用、等待多久、是否泄露内容,以及失败后再次执行能否从干净基线开始。

  1. 在数据库提交前、提交后响应前和副作用发送前分别断开连接,使用同一键重试并核对业务行、通知与配额各只有一次。
  2. 连续执行一百次开始、失败、重试和取消,检查句柄、监听器、队列及临时数据回到基线。
  3. 发布前记录成功率、p50/p95/p99 延迟、错误分类和资源高水位,并为回退条件设定明确阈值。

完成并不等于主路径跑通,而是每个终态都能对账、每个自动动作都受用户意图约束、每个成本都有明确上限。

把方法变成一次真实连接

打开 uCopy,让两台设备在浏览器里安全连接并开始传输。

开始免费使用