一、活动介绍
最近有个项目,拼团的业务,但区别于一般的拼团完成就发货,我们的业务时拼团完成后,有一个抽奖活动,从参加活动的成员中抽出一名幸运儿。
二、代码逻辑
拼团下单的业务如下:
//拼团下单 逻辑
func payMoney()
{
//1、创建采购订单
funcA() {
DB::starttrancs;
//.....业务处理
DB::commit
}
//2、创建支付订单
funcB() {
DB::startTrancs; //开启事务
funcB1(){/*写活动订单,扣库存,加销量....*/};
funcB2(){/*统计funcB的订单数,满员则抽奖...*/};
DB::commit; //提交事务
}
}
三、活动执行流程
活动流程为:
a用户(uid=220)开团;
然后b用户(uid=222) 和 c(uid=217)用户同时参团;
四、现象
这时奇怪的事情就产生了,在funcB方法中 b、c两用户在B2方法中先后统计到的B1的参团人数始终为2人,如下
//b用户在B2方法中的打印:
{
"count": 2,
"qupinkPeople": [{
"id": 1619,
"uid": 220,
"order_id": "wx160439966917278870",
}, {
"id": 1620,
"uid": 222,
"order_id": "wx160439969911969958",
}],
"redis": "2"
}
//c用户在B2方法中的打印:
{
"count": 2,
"qupinkPeople": [{
"id": 1619,
"uid": 220,
"order_id": "wx160439966917278870",
}, {
"id": 1621,
"uid": 217,
"order_id": "wx160439969916075238",
}],
"redis": "3"
}
为方便对比,我们在funcB1方法中对参团人数用redis做了统计:b用户在funB2统计到的实际参团人数为2,c用户在funB2统计到的实际参团人数为3。
结果:导致如果在事务中通过mysql的count()统计参团人数,会出现偏差,即两用户同时参团是无法统计到对方的;
五、解决方案
方案一:
在funcB2前进行事务提交,然后再重新开启一个事务。
可能存在的问题:
方案二:
方案2,把所有funcB1()的由MQ来处理,这样就能顺序处理数据,在消费的时候处理funcB2()
方案三:
欢迎讨论……