java 怎么保证余额_高并发下怎么做余额扣减?

余额的扣减的方式通常有以下几类:

1、基于第三方组件的分布式锁实现

2、for update的行悲观锁

3、基于cas的乐观锁

这几类以及性能优化前面都有说明,我补充一下第三个基于cas导致的ABA问题的解决思路:

ABA问题是由CAS衍生来的,在并发极端情况下会产生,那么什么是ABA问题?

标准的描述如下:

并发1(上):获取出数据的初始值是A,后续计划实施CAS乐观锁,期望数据仍是A的时候,修改才能成功

并发2:将数据修改成B

并发3:将数据修改回A

并发1(下):CAS乐观锁,检测发现初始值还是A,进行数据修改。

上述并发环境下,并发1在修改数据时,虽然还是A,但已经不是初始条件的A了,中间发生了A变B,B又变A的变化,此A已经非彼A,数据却成功修改,可能导致错误,这就是CAS引发的所谓的ABA问题。

举一个游戏充值例子,如下:

按照业务的诉求,事务3是最终将数据库结果值恢复为100,但是通过cas比较更新最终结果出现了40,这个就是ABA导致的问题。

我们以扣款的sql作为例子讲解ABA问题如何解决?

1、数据库表结构由(id、money)修改为(id、money、version)

2、数据库查询由之前的

select money from t_account where id=#{id}

修改为

select money,version from t_account where id=${id}

3、数据库修改除了cas比较外,还需要版本相同,并且进行版本修改

update t_account set money=#{new_money} where id=#{id} and money=#{old_money};

修改为

update t_account set money=#{new_money} where id=#{id} and money=#{old_money} and version=#{version_old}

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值