?
《并发扣款,如何保证数据的一致性?》,分享了同一个用户并发扣款时,有一定概率出现数据不一致,可以使用CAS乐观锁的方式,在不降低吞吐量,并且只有少量修改的情况下,保证数据的一致性。
文章发布不到24小时,就有近200的评论。
其中,问的比较多的是ABA问题,这个问题已经在《并发扣款一致性优化,CAS下ABA问题,这个话题还没聊完!!!》中扩展。 其次,问的比较多的是作业题,为什么一定要用select&set的方式进行余额写回:
UPDATE?t_yue?SET?money=$new_money?WHERE?uid=$uid?AND?money=$old_money;??
为什么不能采用直接扣减的方法:
UPDATE?t_yue?SET?moneymoney=money-$diff?WHERE?uid=$uid;?
很人说,在并发情况下,会将money扣成负数。 为了保证余额不被扣成负数,再加一个where条件:
UPDATE?t_yue?SET?moneymoney=money-$diff?WHERE?uid=$uid?AND?money-$diff>0;?
这样是否可行?画外音:额,撇开业务不谈,这个SQL用列做运算,其实是不好的,建议使用:
UPDATE?t_yue?SET?moneymoney=money-$diff?WHERE?uid=$uid?AND?money>$diff;?
很遗憾,仍然不行。原因在《并发扣款,如何保证数据的一致性?》一文里点赞最多的评论,不幂等。画外音:说明绝大部分同学,能够回答正确作业。 聊幂等性之前,先看另一个测试用例的case。 假设有一个服务接口,注册新用户:
bool?RegisterUser($uid,?$name){?
?????????//查看uid是否已经存在?
?????????select?uid?from?t_user?where?uid=$uid;?
?????????//不是新用户,返回失败?
?????????if(rows>0)return?false;?
?????????else{?
???????????????????//把新用户插入用户表?
???????????????????insert?into?t_user?values($uid,?$name);?
???????????????????//返回成功?
???????????????????return?true;?
?????????}?
}?
有一个测试工程师,对该接口写了一个测试用例:
bool?TestCase_RegisterUser(){?
?????????//造一些假数据?
?????????long?uid=123;?
?????????String?name='shenjian';?
?????????//调用被测试的接口?
?????????bool?result=?RegisterUser(uid,name);?
?????????//预期注册成功,对结果进行断言判断?
?????????Assert(result,true);?
?????????//返回测试结果?
?????????return?result;?
}?
这是不是一个好的测试用例?这个用例存在什么问题?
你会发现,相同条件下,这个测试用例执行两次,得到的结果不一样:
第一次执行,第一次造数据,调用接口,注册成功;
第二次执行,又造了一次相同的数据,调用接口,注册会失败;这不是一个好的测试用例,多次执行结果不同。
什么是幂等性?
相同条件下,执行同一请求,得到的结果相同,才符合幂等性。
画外音:Google一下,比我解释得更好,但意思应该说清楚了。
如何将上面的测试用例改为符合“幂等性”的测试用例呢?
只需要加一行代码:
bool?TestCase_RegisterUser(){?
?????????//造一些假数据?
?????????long?uid=123;?
?????????String?name=’shenjian’;?
?????????//先删除这个伪造的用户?
?????????DeleteUser(uid);?
?????????//调用被测试的接口?
?????????bool?result=?RegisterUser(uid,name);?
?????????//预期注册成功,对结果进行断言判断?
?????????Assert(result,true);?
?????????//返回测试结果?
?????????return?result;?
}?
这样,在相同条件下,不管这个用例执行多少次,得到的测试结果都是相同的。 是不是对幂等性有点感觉了。 读请求,一般是幂等的。
写请求,视情况而定:
insert x,一般来说不是幂等的,重复插入得到的结果不一定一样
delete x,一般来说是幂等的,删除多次得到的结果仍相同
set a=x是幂等的
set a=a-x不是幂等的
…
因此,这么扣减余额:
06-25????来源:澎湃新闻网
09-02????来源:未知
02-20????来源:虎嗅网
02-27????来源:湖北新闻网
03-05????来源:今日头条
04-29????来源:祁东新闻网
04-30????来源:砍柴网
05-10????来源:青岛新闻网
06-04????来源:广西新闻网
06-08????来源:四川新闻网