幂等性设计三种模式:唯一键、状态机与去重表怎么选(幂等性和防重主要实现方式) ypxx.net

2026-08-20· 冯潇· 工程最佳实践

内容摘要

幂等设计有唯一键约束、状态机、去重表三种主流模式:唯一键防重复插入是底线,状态机防重复与乱序更新,去重表防重复消费事件,三者叠加构成完整防线。

核心要点

  • 重试不可避免,幂等是让重试安全的唯一办法
  • 所有同步落库表都应加业务唯一键作为底线
  • 状态机模式天然幂等,还能拦截乱序事件
  • 去重表必须与业务写入同事务,避免假阳性
  • 三种模式叠加使用,而非三选一

幂等为什么是集成的地基

跨系统数据同步中,网络超时、平台限流、下游宕机都会触发重试。如果写入操作不幂等,一次超时重试就可能造成重复下单、重复扣库存、重复记账——这类事故的资损远大于同步延迟。所谓幂等,就是同一操作执行一次和执行 N 次,业务结果完全一致。

模式一:唯一键约束

最朴素也最可靠的做法:给业务表加唯一索引(如 (platform, platform_order_no)),重复写入直接撞唯一约束,捕获冲突后转为更新或直接忽略。

  • 优点:数据库兜底,代码再乱也不会产生脏数据;
  • 缺点:只能防"重复插入",防不了"重复更新";分库分表下唯一键设计变复杂。

所有同步落库表都应以此作为底线,无论上层还做了什么。

模式二:状态机

适合有明确生命周期的单据(订单:已创建 → 已支付 → 已发货 → 已完成)。每次写入携带目标状态,更新时校验当前状态是否允许流转:

UPDATE orders

SET status = 'SHIPPED', updated_at = NOW()

WHERE platform_order_no = 'TB20260001'

AND status IN ('PAID', 'SHIPPED'); -- 只允许从已支付流转;已是 SHIPPED 则空转

状态机天然幂等:重复推送同一状态,第二个请求命中空集,无副作用。它还能顺便拦截乱序事件(先收到"已发货"再收到"已支付"时,可按业务规则拒绝或排队)。

模式三:去重表

适合"事件流"场景:为每个事件分配唯一 ID,消费前先向去重表插入 (consumer, event_id),插入成功才继续处理,冲突说明已消费过。去重表要与业务写入在同一事务中,否则宕机窗口会出现"去重记录写了、业务没写"的假阳性。

三种模式怎么选

实践中三者是叠加而非互斥:去重表挡住重复事件,状态机约束流转,唯一键做最后兜底。轻易云的可视化集成方案中,每条数据流默认开启"按业务键幂等写入",并为订单类实体预置状态流转校验,接入方无需自行实现这套机制。