web应用账户金额的并发问题

本文探讨了在并发情况下,使用MySQL和Java处理用户账户金额扣除时遇到的问题。原来的方法可能导致并发扣除不准确。为解决此问题,首先尝试使用Redis作为并发锁,但影响了并发效率。最终提出了一种改进的SQL解决方案,通过在更新时直接减去金额,并结合条件判断,确保数据安全的同时,提高了并发性能。
摘要由CSDN通过智能技术生成

项目使用的是mysql数据库,使用的是mysql默认的repeatable read事务级别, 今天需要讨论的是,用户消费业务账户金额扣除的并发性问题。

消费业务代码肯定是用spring的事务管理的。

一开始的代码是这样的,里面加了一些非sql的东西,帮助理解下业务。

begin;
set @value=select value from test where id=1

//xxxx@p金额的各种校验处理,比如大于零等等

set @newvalue=@value-x //x是消费金额
update test set value=@newvalue where id=1 and value-1>=0;
commit;

看起来毫无问题。先查询账户金额,然后java代码处理扣减后的金额得到newvalue,最后更新newvalue到数据库。

现在问题来了,在并发情况下,两个session同时执行这段代码,假设同时读到@value=1,然后消费1,同时计算出newvalue=0。即时mysql的update是自带排它锁阻塞的,那么两个session还是各自跑完了,但是用户余额却只扣除了1,而不是2!

为了解决这个并发问题,一开始的想法就是加锁,又由于服务器是多个tomcat的,因此sych同步显然不合适,于是使用了redis来作为集群的并发锁,控制消费业务代码,在第一步获取账户余额value的时候就进行了代码锁定,直到消费业务完成才释放锁。

这么做,其实只是保证了数据的安全,但是却大大降低了并发效率,把本

评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值