轻易云
注册体验

幂等性设计三种模式:唯一键、状态机与去重表怎么选

· 系统管理员· 工程最佳实践· 4 次浏览· 约 2 分钟读完
幂等数据一致性订单同步库存同步API 编排

幂等为什么是集成的地基

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

模式一:唯一键约束

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

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

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

模式二:状态机

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

sql
UPDATE orders
SET status = 'SHIPPED', updated_at = NOW()
WHERE platform_order_no = 'TB20260001'
  AND status IN ('PAID', 'SHIPPED');  -- 只允许从已支付流转;已是 SHIPPED 则空转

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

模式三:去重表

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

三种模式怎么选

模式防什么适用场景成本
唯一键约束重复插入一切落库写入(底线)极低
状态机重复/乱序更新订单、售后单等有生命周期的单据
去重表重复消费事件MQ 消费、Webhook 推送

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

本文为原创内容,转载请注明出处:/insights/engineering/idempotency-design-patterns

评论