售后更新出现问题分析-幂等和防重

2024-08-27 早上测试提交BUG,说售后单状态流转不对,吓得我一激灵,赶紧打开IDEA 查看代码,发现售后这块代码没有动过呀,咋回事?

流程是这样的: 测试模拟用户下单,提交订单后付款,然后用户又进行退款操作,需要商家审核售后,商家审核通过的话,进行退款操作,售后单更新状态售后完结。

然后这个单据进行了退款操作,但是售后单状态没有完结。

自己又顺着测试的步骤操作了一遍,也没有复现问题,测试自己也不能没有这个问题。

没有办法,硬着头皮下载日志回来看看吧!

这两个单都是未发货退款,500002280004 正常售后退款成功,

500002280003 退款成功但是售后状态不对

直接在日志里面查询售后单号:

发现这个售后单在不到 0.1秒 请求了两次,整个售后退款流程代码一秒才完成

即使在代码对售后状态进行了校验也是无用,因为并发请求时,上一个售后代码没有执行完成,事务没有提交,新来的请求读取的售后状态也是未完结的,可以继续往下执行代码,

执行到退款代码时,该同学意识到可能重复退款,加了一把分布式锁,也算不幸中的万幸,没有造成重复退款

那么我现在要做的就是在在售后接口进行防重,先说一下方案,就是在入口处添加一把分布式锁,获取到锁就往下执行,代码执行完成,删除锁,防止并发重复请求。

详细分布式锁使用可以看我的另一篇文章:

AOP自定义注解防重-CSDN博客

再来说一下幂等和防重的概念:

幂等性和防重复是确保软件系统正确性的重要概念。下面通过一些具体的例子来解释这两个概念:

### 幂等性(Idempotence)

1. HTTP GET 请求:当你对一个 HTTP GET 请求进行多次调用时,比如请求一个网页,无论请求多少次,返回的网页内容都是相同的。这就是幂等性的体现。

2. 数据库更新操作:假设有一个 SQL 更新语句 `UPDATE users SET age = 30 WHERE id = 1`。无论这个语句执行一次还是多次,只要条件 `id = 1` 不变,用户1的年龄都会被设置为30岁。

3. 设置键值对:在 Redis 中使用 `SET` 命令设置一个键值对是幂等的。比如 `SET key value`,无论执行多少次,只要键名不变,键对应的值都会是最后一次设置的值。

4. 删除操作:删除一个文件或数据库记录的操作也是幂等的。无论执行多少次,文件或记录只会被删除一次。

### 防重复(Idempotent Message Processing)

1. 订单系统中的唯一订单号:在订单系统中,每个订单都有一个唯一的订单号。当处理订单时,系统会检查订单号是否已经存在,如果存在,则不会重复处理同一个订单。

2. 消息队列中的消息唯一标识符:在消息队列中,每条消息都有一个全局唯一的标识符。消费者在处理消息前会检查这个标识符,如果已经处理过,则不会再次处理。

以下是一些具体的例子:

1. 支付系统:在支付系统中,每次支付请求都会生成一个唯一的交易ID。即使支付请求因为网络问题被重复发送,系统也会通过检查交易ID来避免重复扣款。

2. 银行转账:当你通过银行应用进行转账时,每次转账操作都会生成一个唯一的交易号。即使你多次点击“确认转账”,银行系统也会通过交易号来确保转账操作只执行一次。

3. 社交媒体发帖:在社交媒体平台上,当你发布一条帖子时,即使因为网络延迟你多次点击“发布”,平台也会通过检查帖子的唯一标识符来确保你的帖子只被发布一次。

4. 邮件发送:邮件发送系统通常会为每封邮件分配一个唯一的消息ID。即使因为某些原因邮件发送请求被重复触发,系统也会通过消息ID来避免重复发送同一封邮件。

通过这些例子,我们可以看到幂等性确保了操作重复执行不会产生副作用,而防重复机制则是通过系统设计来避免操作被重复执行。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值