面试官:接口幂等性怎么保证?并发场景下的三层防御体系

面试官:接口幂等性怎么保证?并发场景下的三层防御体系

在近期的一次后端面试中,一位拥有四年经验的候选人被问及“接口幂等性如何保证”。他迅速给出了标准答案:请求携带唯一流水号,利用 Redis 存储执行标记,执行前判断、执行后更新,重复请求直接拦截。

然而,当面试官抛出一个真实的线上事故场景时,这位候选人陷入了沉默。

幽灵陷阱:并发下的幂等击穿

假设订单支付接口采用了标准的幂等方案:请求带唯一支付流水号,执行前查 Redis 标记,无标记则执行支付逻辑,执行完写入过期标记。自测和压测均未发现重复支付。

但在大促当天,十几笔订单出现了重复扣款。用户付了两次钱,后台生成了两条支付流水。排查发现:

  1. 两次请求的流水号完全一致。
  2. Redis 中确实留存了执行标记。
  3. 日志显示两次请求几乎同时到达,间隔不到 10 毫秒。
  4. 全程无报错,幂等校验看似完全失效。

候选人猜测是 Redis 查询超时,但面试官指出 Redis 集群正常,响应为毫秒级,且事后用同一流水号重试确实能被拦截。问题核心在于:并发同时到达时,校验与执行之间出现了时间窗口,导致幂等防护被击穿。

并发请求击穿幂等校验的时间窗口

这正是接口幂等性最隐蔽的陷阱。许多开发者认为背熟“查、执、写”三步法就能万无一失,却忽略了并发请求穿透、标记过期冲突、降级场景校验失效等问题。这些漏洞往往不报错、不告警,直到造成实打实的重复支付资损才被发现。

为什么这道题能筛出高手?

这道题考察的不仅仅是是否会写幂等代码,而是并发视角下的幂等可靠性设计思维。一个能守住核心资金链路的后端工程师,必须建立三层防御体系。

接口幂等性三层防御体系架构

第一层:业务分级,差异化幂等方案

并非所有接口都需要同等强度的幂等保护,应根据业务重要性进行分级:

  • 强幂等场景(核心支付、订单创建、库存扣减)
    • 采用分布式锁串行化校验。
    • 执行前先加锁,再校验,从根源消除并发穿透的时间窗口。
  • 弱幂等场景(状态更新、通知推送)
    • 使用 Redis 标记 + 过期时间 即可。
    • 接受极低概率的重复执行,以换取更高的性能。
  • 拆分幂等粒度
    • 按业务场景独立生成流水号与标记,避免不同业务复用同一幂等键导致的误拦截或漏校验。

强幂等与弱幂等场景的分级策略

第二层:兜底校验与异常容错

即使上层逻辑完美,底层数据一致性仍是最后防线:

  1. 数据库唯一索引
    • 为核心业务流水号添加唯一索引。
    • 即使上层所有幂等逻辑失效,数据库层也能确保绝不会出现重复数据落库。
  2. 幂等有效性监控
    • 统计重复请求拦截率、重复数据发生率。
    • 指标异常时自动告警,及时发现潜在问题。
  3. 优化执行时序
    • 在高并发场景下,采用**“先写标记,再执行业务”**的方案。
    • 标记写入成功才允许执行业务;若执行失败,主动回滚标记。
    • 此举填补了“校验”与“执行”之间的持续漏洞,防止并发请求同时通过校验。

先写标记再执行的时序优化

第三层:架构层优化,从根源降低风险

从系统架构层面统一规范,避免各业务线各自为战导致的时序与逻辑漏洞:

  • 统一幂等组件
    • 标准化加锁、校验、标记、过期全流程。
    • 避免重复造轮子带来的不一致性。
  • 入口层排队收敛
    • 针对相同流水号的请求,在入口层进行排队收敛。
    • 相同幂等键的请求串行处理,从入口消除并发穿透可能。
  • 大促强幂等模式
    • 在核心时段开启“分布式锁 + 数据库唯一约束”双重生效模式。
    • 宁可牺牲少量接口吞吐量,也绝不允许核心资金链路出现重复执行的资损事故。
总结:从代码到工程思维的升级

这道面试题的本质,是考察开发者是否从“会加个幂等校验”升级为“设计全场景高可靠幂等保障体系”的工程思维。

普通开发认为查一下 Redis、写个标记就是幂等的全部;而高级工程师深知,在并发请求的时间窗口面前,接口幂等是一把双刃剑。一个时序细节的疏忽,就可能引发重复支付、重复下单等严重线上事故。

构建高可靠的幂等体系,需要业务分级、兜底校验与架构优化的协同作用。只有建立起多层次的防御机制,才能在复杂的分布式环境中,真正守住数据一致性的底线。