拉卡拉开放平台
用户不耐烦多点了一次按钮,网络抖动让请求重发了一次,通知机制把同一条消息送达了两次——在支付场景里,重复是常态,不是异常。幂等就是让系统对「同一件事发生多次」保持同一结果的能力。
最直观的后果是多扣一次钱、多退一次款,或者把同一个通知执行成两条业务记录。更隐蔽的后果是对账困难:两侧记录笔数对不上,追查时无法区分「业务确实发生两次」与「同一件事被记了两次」。
粒度太粗,正常的第二笔会被误伤;粒度太细,重复请求拦不住。常见的做法是以业务单据为粒度——同一单的多次提交视为同一件事,不同单各归各。标识优先用业务自身的单号,而不是每次随机生成,后者根本起不到识别重复的作用。
幂等判断与业务写入必须在同一个事务里。两步分开时,总存在「标识已落库、业务未完成」或相反的窗口,恰好在这个窗口里的重复请求会绕过保护。把两件事绑在一起,窗口就消失了。
| 粒度 | 做法 | 后果 |
|---|---|---|
| 过粗 | 按天或按用户生成 | 正常的不同请求被误判为重复 |
| 合适 | 按一次业务意图生成 | 重复被拦住,正常请求不受影响 |
| 过细 | 每次重试都重新生成 | 幂等形同虚设,重复照样发生 |
退款动作如果缺少幂等保护,一次网络重发就可能退两次;分账动作同理,重复指令会让同一笔钱被分配两次。
下单环节的重复还有机会通过后续对账纠正,退款与分账环节的重复直接造成资金差错,因此这两处的幂等要求比下单更严格。
幂等依赖一份「已经处理过」的记录,这份记录本身也需要设计:
两个相同请求几乎同时到达时,单纯的顺序判断会失效——两边都查不到记录,于是都往下执行。因此幂等判定与记录写入需要是一个整体动作,要么靠唯一约束,要么靠原子操作。
先查再写看似合理,在并发下却是最典型的漏洞形态。
异步链路上的重复更难察觉:通知重复、任务重试、消息重投,每一环都可能带来一次重复处理。
三层都覆盖之后,重复才真正变成一件无害的事,而不是需要处处提防的隐患。
幂等不是某个接口的附加要求,而是整个支付链路的底层假设。从下单到退款,从通知到分账,每一处涉及资金动作的地方,都应该默认「这个请求可能会来第二次」。把这个假设写进设计文档的第一页,比事后补一百次补丁都有效。
从这个角度看,幂等不是一项可选优化,而是支付系统里默认就该存在的一层保护。把它放在设计阶段的起点,而不是出问题之后的补救清单里,整个链路的可靠性会有明显不同。
换句话说,幂等保护的是资金安全,而不只是接口调用的整洁度。它的收益平时看不见,只在重复真正发生的那一刻才会显现出来,而那一刻往往是业务最忙的时候。
24小时免费咨询
请输入您的联系电话,座机请加区号
