韧性与并发防御
用于重复请求、竞争写入、依赖失效或部分成功会破坏业务正确性的任务。先明确不能发生的结果,再选最少的防护机制。
并发与重复副作用
从不变量推导约束,例如“订单只扣一次款”“库存不为负”。沿同一操作列出会改变其有效性或结果的参与者,检查“校验后状态改变”“取消后动作仍完成”“恢复尚未结束执行者退出”等真实可能的交错,再选择机制。界面按钮禁用或再加一次非原子检查,不能代替服务端一致性约束。
| 冲突 | 可选机制 | 验证重点 |
|---|---|---|
| 重复创建 | 业务唯一约束或幂等记录 | 并发同键只有一个结果;冲突如何返回 |
| 丢失更新 | 版本号条件更新、行锁或事务隔离 | 冲突可检测,重试有界 |
| 资源扣减 | 带余额条件的原子更新或事务 | 多请求下不变量仍成立 |
| 跨进程排他 | 确有必要时用分布式锁 | 租约过期、崩溃和旧持有者继续写入 |
跨表操作不默认用分布式锁,先评估数据库能力。采用锁时考虑续租、所有权校验,必要时用 fencing token(拒绝过期持有者的版本凭证);只有 TTL 不能保证正确性。
原子性与跨边界一致性
同一数据库内需要同成同败的写入使用合适的本地事务,不把无关写入或长时间外部调用塞进事务。
跨系统先确定允许部分成功、补偿还是最终一致,再选择查询对账、补偿任务、状态机、消息队列或 Outbox。Outbox 在本地事务同时写业务和待发送事件,适合两者不能丢一边的情况,不保证仅投递一次;仍需消费去重、重放和积压监控。无此需求不引入整套设施。
超时、重试与降级
依据用户等待预算和依赖延迟设置连接与总超时,不统一写死阈值。重试只用于可恢复且不会重复产生副作用的情况,限制次数、退避并增加抖动,避免各层重试放大流量。
超时或取消不保证远端动作停止。需要时保留操作标识和恢复责任,通过结果查询、终结确认或补偿处理迟到结果;不得仅因本地期限已到、授权已清除或当前看似未发生副作用,就宣布结束。例如导出任务取消时文件可能仍在写入,清掉任务记录会丢失随后删除临时产物的责任。具体保留与清理政策由业务规则决定。
恢复未完成时,正常停止、更新或卸载也要安排责任交接,或明确拒绝结束;异常崩溃则按失败代价设计重启恢复或其他接管方式。不能在报告成功后留下无人处理的副作用。降级不能暗中改变业务承诺。
故障注入使用隔离环境,优先模拟超时、重复消息和竞争窗口;未经授权不切断用户网络或停止服务。