支付幂等:一锁二判三更新

一、前言

古人云:"一命;二运;三风水;四积功德;五读书。"

回顾过去的一年,公司的故障报告里 防重复问题 反复出现,比如:

  • 人民币钱包付款:只付款了一次,但是系统付了两笔,两笔的创单间隔时间是5s
  • 领取奖励金重复:重复获得 -> 盗刷
  • 疑似重复入账:平台背后的支付机构汇款异常,一笔交易打款两次(导致给客户入账两笔资金)
  • 等等

此类问题归类于没有做好幂等,那么幂等是什么

对同一操作重试任意多次,系统的最终状态,以及对外可观测的结果不变;为容错与重试而生。

  • 网络问题 / 前端操作抖动,造成重复提交,后台系统仅处理一次。

针对这类问题,有一个口诀:一锁二判三更新

  • 一锁:先对同一业务唯一单号加锁,串行化并发请求,避免同时修改同一份数据。
  • 二判:拿到锁后先判定是否已处理过/是否允许处理(幂等判重、状态判定、业务约束)。已处理则直接返回历史结果,不再执行。
  • 三更新:要落库幂等记录(带唯一幂等键),重复请求直接命中并返回相同结果。

案例分析:资金安全

以下是3个案例场景。

案例一:防重复扣款(不要轻易换单)

用户下单场景:

  • 易错 1:向账户系统,重复扣余额
  • 易错 2:重复向渠道扣款

问题:如果扣款 / 扣余额步骤超时了,该怎么办?

即出现了中间态,可以先查询请求情况,再重试。

  • 超时关单不可取:可能账务系统那扣款成功了。

Tips:避免重复有如下准则

  • 扣钱时:先扣钱再处理业务
  • 加钱时:先处理业务再加钱

案例二:防重复入账

海外电商平台入账:平台收款

  • 各大银行通过 H2H方式/人工上传,解析入账文件,获得客户的银行入账流水信息
  • 根据店铺信息定期拉取账期数据
  • 根据亚马逊账单和银行流水,符合匹配规则后,进行入账

存在特殊入账:

  1. 银行钱先到,账期数据还没到
  2. 亚马逊 API 授权关闭了,但钱打过来了
  3. 等等

疑似重复入账:平台背后支付机构汇款异常,一笔交易打款两次,即入金 2 笔。

  • 后续银行直接按ACH debit 将资金从账户中扣除

案例三:防重复结算

支付场景是实时的,但要将钱打给商户要通过清结算系统。

  • 易错:重复结算、重复打款。

解决:

  1. 上下游单据一致性核对:支付 - 清结算,单据一致核对(笔数、金额)。
  2. 打款拦截:打款前规则判断,比如:每日打一次款。

二、实际工作中使用

实际工作中,通常采用组合拳方式:分布式锁 + 数据库兜底

  • "分布式锁"实现幂等:因为锁丢失 / 续约失败,仍有重复
  • 幂等表:用唯一约束 + 去重表做最终保障

代码如下:

1、分布式锁,一般使用 Redis,封装对应锁工具

java 复制代码
@RedisLock(lockName = "order", key = "#req.reqId")
public OrderResponse order(Req req) {
    // 业务处理
}

2、幂等表

java 复制代码
public void saveOrder(TradeOrder tradeOrder) {
    Order order = (Order) tradeOrder;
    transactionTemplate.execute(status -> {
        //幂等表
        repeatRepository.save(order);
        //订单表
        orderRepository.saveOrder(order);
    });
}
相关推荐
一点程序8 小时前
基于SpringBoot的选课调查系统
java·spring boot·后端·选课调查系统
怪兽源码10 小时前
基于SpringBoot的选课调查系统
java·spring boot·后端·选课调查系统
csdn_aspnet11 小时前
ASP.NET Core 中的依赖注入
后端·asp.net·di·.net core
昊坤说不出的梦12 小时前
【实战】监控上下文切换及其优化方案
java·后端
疯狂踩坑人12 小时前
【Python版 2026 从零学Langchain 1.x】(二)结构化输出和工具调用
后端·python·langchain
橘子师兄13 小时前
C++AI大模型接入SDK—ChatSDK封装
开发语言·c++·人工智能·后端
@ chen13 小时前
Spring事务 核心知识
java·后端·spring
一点技术15 小时前
基于SpringBoot的选课调查系统
java·spring boot·后端·选课调查系统
RANCE_atttackkk15 小时前
Springboot+langchain4j的RAG检索增强生成
java·开发语言·spring boot·后端·spring·ai·ai编程
好好研究17 小时前
Spring Boot - Thymeleaf模板引擎
java·spring boot·后端·thymeleaf