后端接口重复提交怎么办?用幂等键把一次操作做成一次
重复提交几乎不是用户手抖,而是网络重试、页面重复点击、消息重复投递造成的。同一笔操作被执行两次,后果可能是重复扣款、重复发货、重复建单,所以后端接口要做到:同一个请求,无论来几次,最终效果只发生一次。这就是幂等。
最实用的做法是幂等键。客户端为每一次业务操作生成一个唯一键,随请求一起发过来,常见做法是放在请求头 Idempotency-Key 里,键的粒度必须是业务操作本身,比如一笔订单、一张工单,而不是用户ID加时间戳。服务端收到后先查这个键:如果已经处理过,直接返回第一次的结果,不要报错、不要重新执行;如果没处理过,在同一个事务里把业务操作和幂等记录一起落库,键上建唯一索引,靠数据库唯一约束兜底并发重复。
只靠幂等键还不够,业务本身也要能安全重放。订单、工单这类对象适合用状态机:只有待处理状态才能流转到已处理,已处理状态再收到同一请求就直接返回,不再流转。库存、余额这类数值变更不要用先读后写再覆盖,改用带条件的更新,比如 update stock set stock = stock - 1 where id = ? and stock >= 1,靠影响行数判断是否成功,避免两次扣减。
第三个常见坑是去重表和业务表不在同一个事务里。先写去重记录、后做业务,中间一断电就会出现去重已记、业务没做,下次重试被误判为已处理;先做业务、后写去重,重复请求又会穿透。所以幂等记录、业务写操作、状态变更要放在同一个本地事务里,跨服务时再用事务消息或最终一致的补偿来收尾,不要把幂等做成事后对账。
落地前按这张清单自查一遍:幂等键是不是业务级唯一、过期时间是不是合理(太短会误重放,太长会占着键不放)、重复请求返回的是第一次的结果还是错误、并发重复有没有唯一索引兜底、失败重试会不会把半成品当成已完成。把这五项做对,重复提交就从线上事故变成一句可以安全重试的普通请求。
- 点赞
- 收藏
- 关注作者
评论(0)