接口幂等基础题:重试安全不是后端玄学

📅 2026/7/7 12:39:29 👁️ 阅读次数 📝 编程学习
接口幂等基础题:重试安全不是后端玄学

接口幂等基础题:重试安全不是后端玄学

一、幂等不是“多点几次也没事”的口号

后端基础面试里,幂等是高频题。很多回答会说“加唯一键”“用 Redis 锁”。这些都是手段,不是定义。幂等的意思是同一个业务请求执行一次和执行多次,最终效果一致。

接口幂等不是为了好看,而是为了处理重试、超时、网络抖动和用户重复点击。没有幂等,重试会把一次业务变成多次副作用。

二、先定义业务唯一请求

幂等设计第一步是找到业务唯一键。支付是订单号,消息发送是消息 ID,创建任务可以是客户端生成的 request_id。

flowchart TD A[客户端请求] --> B[携带幂等键] B --> C{是否处理过} C -->|是| D[返回历史结果] C -->|否| E[执行业务] E --> F[记录结果] F --> G[返回响应]

没有幂等键,就很难判断两次请求是不是同一件事。服务端猜不出来。

三、用数据库唯一约束兜底

Redis 可以加速,但数据库唯一约束才是关键兜底。

CREATE TABLE idempotency_record ( idempotency_key VARCHAR(128) PRIMARY KEY, status VARCHAR(32) NOT NULL, response_body TEXT, created_at TIMESTAMP NOT NULL );

处理请求时,先插入幂等记录。插入成功说明第一次处理,主键冲突说明已经处理过或处理中。具体状态要区分。

四、处理中状态要谨慎返回

如果第一次请求正在处理,第二次请求来了,不能直接说成功。可以返回处理中,或者等待一小段时间查询结果。否则客户端会误以为业务已经完成。

还要保存响应结果。第一次成功后,后续相同幂等键应返回同样语义的结果。不要重新执行一遍业务。

最后,幂等记录要有过期策略。保存太短,重试窗口内会失效;保存太久,表会膨胀。过期时间要按业务重试周期定。

幂等还要处理“成功但响应丢失”的情况。服务端业务已经完成,网络断了,客户端重试。此时服务端应返回第一次成功的结果,而不是再执行一次。保存 response_body 的价值就在这里。

处理中状态也要有超时恢复。任务卡住后,幂等记录一直是 processing,后续请求都会被挡住。可以记录更新时间,超过阈值后进入可恢复流程,但恢复前要确认业务是否真的未完成。

写接口和读接口的幂等要求不同。GET 天然应无副作用,POST 创建资源通常需要幂等键,PUT 更接近覆盖语义。面试回答时先区分接口语义,会比直接说 Redis 锁更靠谱。

最后,幂等和分布式锁不是一回事。锁控制并发,幂等控制重复请求的业务结果。锁释放后重复请求仍然可能再次执行,所以最终还得有业务唯一约束兜底。

幂等记录要和业务事务尽量放在一起。先写业务表,再写幂等表,中间失败会留下灰色状态;先写幂等表,再执行业务,也要处理业务失败后的状态回滚。面试时能讲出事务边界,会比只说“加 Redis”扎实很多。

消息消费也需要幂等。队列通常是至少一次投递,同一消息可能被处理多次。消费者可以用 message_id 做幂等键,业务表用唯一约束兜底。重复消息来时,返回已处理即可。

最后,幂等不是万能补丁。请求本身如果没有稳定业务键,后端很难判断重复。客户端、网关和服务端要一起约定幂等键,单靠某一层猜不出来。

测试幂等时,不要只测连续两次成功请求。还要测第一次超时、第一次业务成功但响应失败、第一次处理中服务重启、第二次并发到达。幂等问题最容易出现在这些尴尬中间态。

五、总结

接口幂等的核心是定义业务唯一请求,并保证重复请求不会产生重复副作用。幂等键、状态记录、数据库唯一约束和历史结果返回是基础。重试安全不是玄学,是后端系统必须写清楚的一条合同。