高并发和锁

为了学习高并发,我们从一个例子着手。
商店里库存了一批橘子,得益于老板的宣传造势,已经有大量顾客被吸引,准备在某天12点开抢。但是,如今需要面对的问题是高并发,如何保证在抢购过程中数据库不会出现数据不一致的情况?
我们都可以用锁的机制来处理并发。

抢购过程并非原子的,可以做如下分解。(1和2这两步,分别用两个sql语句来实现)

  1. 获取当前剩余库存,如果库存数大于购买数量,可以购买。
  2. 更改剩余库存数(剩余库存数 = 原库存数-购买数)。

事务和隔离级别

无论采取何种机制,设置事务和隔离级别。如果抢到,则执行正常流程;如果没有抢到,则应该确保正常退出流程。隔离级别在此前提到过,数据库有四种隔离级别,用于在不同程度压制事物之间的相互干扰。

在Spring Boot中设置事务直接用@Transactional,设置隔离级别用属性isolation或者在配置文件中。

悲观锁

在查询库存的sql语句中,添加一个排他锁:for update。这表示在事务执行到查询库存时,它将阻塞其余事务也执行该请求,从而应对高并发。
悲观锁呈现一种“悲观”的态度,排他、独占,会阻塞进程,因此在一定程度上会损耗性能。

乐观锁

另一种解法是乐观锁,它要求在表中增加一个version请求,读取库存时会获取原有的version充当“旧值”,更改库存时会比照原库存记录中的version是否和“旧值”相同:

  • 如果不同,表明该事务处理过程中已经被其他事务影响了,原有数据是不可信的,所以不能再在此基础上做修改了。
  • 如果相同,表明该事务没有受到其他事务的影响,可以继续执行。再执行完毕后,会将version+1表明已做出更改。

乐观锁不是独占的,它“乐观”地认为各事务会按照先后顺序依次执行,但同时保持警惕,如果被“冒犯”了,它将取消本次操作。

当然,我们不可能让一个用户发出请求后返回一个取消请求。我们需要做的是添加一个循环体,可以依据时间,也可以依据循环次数,对那些回滚的事务再次处理。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值