Java 面试题

接口幂等性设计:Token、唯一键、状态机五种方案

"创建订单"接口在网络重试场景下怎么保证幂等?

为什么面试官会问这道题

重试无处不在(移动网络、webhook回放)。高级工程师要会主动设计幂等,而不是寄希望客户端"小心重试"。

如何回答

  1. 1

    方案1:客户端带幂等Key(UUID)在header。服务端存(key→结果)。同Key直接返回缓存。

  2. 2

    方案2:业务唯一键DB唯一约束(如out_trade_no)。重复插入抛异常,捕获后当成功处理。

  3. 3

    方案3:状态机保护——UPDATE…WHERE status='PENDING'——只有第一次翻状态,后续0行。

  4. 4

    方案4:Redis SETNX+TTL当轻量锁——第一个赢,重试看到token直接返回。

  5. 5

    方案5:悲观锁(SELECT…FOR UPDATE)锁聚合根。简单但高争用下吞吐掉一大截。

参考回答示例

创建订单我会组合两招:客户端在header带Idempotency-Key(SDK生成UUID),orders表这个字段加唯一约束。服务端INSERT…ON CONFLICT DO NOTHING RETURNING *。rows=1是新建、rows=0就SELECT返回已有订单——两条路径都是确定的。Idempotency-Key行有后台任务24小时后清。对下游副作用(扣款、锁库存)再叠状态机——转移条件WHERE status='PREV',重复事件没法二次扣款。看起来双保险,其实链路里每一段都有自己的重试行为,我要系统扛得住它们同时犯病。

实用技巧

  • 别信"客户端说不重试"——网关、LB、用户都会重试。

  • 幂等Key要按用户做隔离——跨用户碰撞是安全漏洞。

  • 即答侠按"成本由低到高"摆这些方案——答出成本意识面试官印象深。

常见问题

GET天然幂等吧?

规范上是的,实践中缓存、埋点副作用、读-后-写都能让GET变得不幂等。当作啥都不白给来设计。

幂等 vs 恰好一次?

幂等=重试安全;恰好一次=副作用只发生一次。后者更强,通常是幂等+去重窗口一起做。

面试时担心忘词?即答侠实时助你

即答侠 AI 实时监听面试对话,自动识别问题并即时生成回答建议——无感辅助,让你从容应对每一道题。

免费试用即答侠