查询并修改场景下扣款操作保持数据一致性
用户购买商品逻辑伪代码如下
1,计算用户购买商品的价格,比如是10元
2,查询用户余额

select money from user where user_id = 1;  // 例如结果是100

3,计算扣款后的价格 100 - 10 = 90
4,更新用户余额

update user set money = 90 where user_id = 1;

以上在并发的情况下会出现数据不一致
如果考虑并发的话可以以每个用户为维度加上分布式锁,没有抢到锁的提示失败。
对于小概率的数据还可以这样做
在第四步更新用户余额修改为(where条件增加查询时的初始值)

update user set money = 90 where user_id = 1 and money = 100

并发“查询并修改”的场景,可以用CAS(Compare and Set)的方式解决数据一致性的问题

这种方式会带来其他新的问题,例如ABA问题
例如有下操作:
并发1(上):获取出数据的初始值是A,后续计划实施CAS乐观锁,数据仍是A的时候,修改成功
并发2:将数据修改成B
并发3:将数据修改回A
并发1(下):CAS乐观锁,检测发现初始值还是A,进行数据修改,并成功了
余额操作,出现ABA问题并不会对业务产生影响,因为100对应的都是100块钱

解决ABA问题,只需加入版本号的概念,则优化后是
1,计算用户购买商品的价格,比如是10元
2,查询用户余额

select money,version from user where user_id = 1;  // 例如结果是money=100 version = 1

3,计算扣款后的价格 100 - 10 = 90
4,生成新的版本号 例如 version =2
4,更新用户余额

update user set money = 90 and version = 2 where user_id = 1 and version = 1 ;