一、问题描述:
用户在购物的一个订单中使用了3000多比红包;红包是平时通过签到分享获得的,每笔几分到几毛钱。我们系统整个订单流程大概是,用户加车的时候会计算可以用多少钱的红包,并将计算结果保存在一个订单奖励明细表中,记录的状态为待处理;提交订单的时候我们会扣账户下对应的红包,并将订单奖励明细表中的状态改为已发放,提交订单的数据库操作包括扣减用户账户下的红包、更新明显表的状态为已发放,记录审计记录,记录用券资源通知记录等表,这些表的操作都是在一个事务中进行的,并且我们会判断数据库实际的更新条数和预计要跟新的条数是否一致,如果不一致会回滚数据,也就是做了数据库防并发处理,所以这些表要么都操作成功要么都失败,但是实际在定位问题的过程中发现红包被扣了,但是明细表数据没了;提交订单业务执行时间花费了9秒,正常的超时或者异常回滚会加回红包,更新明显状态数据为待处理,与实际的现状不符合;会删除明显表的操作是在加车的时候,加车的接口我们会计算优惠,并将优惠数据记录到奖励明细表中,记录前我们会先根据购物车的单号做下防重复判断,如果单号之前已经提交过订单会报错,如果单号之前没提交过订单,我们会删除单号之前记录的优惠数据,将新的优惠计算结果也就是用红包的结果记录下来,但是由于删除之前数据的时间我们没有带上原来的状态去删除导致数据被删除了。
二、接口执行顺序逻辑描述
【1】、购物车接口
a、防并发
b、其他业务逻辑
c、计算活动、券、红包的优惠
d、根据单号查询该单之前是否以提交订单
e、如果未提交订单则删除之前数据,记录新的数据;在事务中操作
【2】、提交订单的接口
f、防并发
g、优惠匹配校验等其他业务逻辑判断
h、在事务中跟新红包、券、记录订单奖励明显等
该问题产生的原因是用户在第一次加购物车,然后提交订单后,由于提交订单的时间长,提交订单没处理完,他退出到加车的业务去了,同一个订单号又调用了购物车的接口,在h操作执行完前d操作发现订单未提交,然后h操作执行完成,接着e操作将明显数据删除了
三、问题原因分析,与解决办法
【1】购物车的接口和 提交订单的接口用的不是一个防并发锁:我们不能将两个接口并发锁改成一个,否则与设计原则不符。
【2】两个接口交替执行,数据删除操作的时候没有带着原预期状态去删除,因此我们的处理办法是删除的时候带着原来的预期状态(待处理状态去删除),然后购物车的接口也判断插入条数是否与计算的条数一致,不一致返回加车失败。