秒杀系统中乐观锁(Optimistic Lock)和悲观锁(Pessimistic Lock)的对比

参考九章的讲座。
悲观锁:用户先判断是否拿到锁,如果没有拿到,则排队等待。若可以拿到,则减库存,然后释放锁,这时排队等待的线程有一个可以得到锁。

SQL实现: 注意"for update"表示执行完step 1语句后,把product_id = xxxxx 锁住,其它线程则不能对product_id = xxxxx操作。

//step 1:
select * from stock where product_id = xxxxx for udpate
//step 2:
udpate stock set count = count - 1 where product_id = xxxxx and count > 0

缺点: 1) 会占用大量线程资源,因为一个线程更新不成功,其他线程全部等待。比如说Mysql的线程资源全部耗尽,从前端客户的角度看起来是一直在等待。2) 更新会很慢。
使用场景:在流量不大,对数据一致性要求又非常高的时候,可以用悲观锁。


乐观锁:我不锁,先更新。更新失败了再重新来过

注意这里更新是要结合版本号。如果结合版本号查询有库存,则扣库存, 否则说明版本号被更新。


SQL实现:
查version字段,如果相等,说明可以更新,同时把version+1,否则说明更新失败(因为其他线程更新过了)。

udpate stock set count = count - 1 and version = verison + 1 where product_id = xxxxx and count > 0 and version = xxxxx

一个更新失败的例子:
1. select version 1
2. do some logic. At this time, another thread change the verison to 2
3. update stock version param 1 //发现失败了,则更新version to 1,再重新来过。 

使用场景:如果只要保证数据最终一致性,可以用乐观锁。
秒杀场景不适合乐观锁,因为verion字段会一直变! 后台会一直忙于更新,大量线程hold住。

个人总结:从上面可以看出, 因为MySql的并发量很低(单机1000),无论乐观锁和悲观锁好像都不适用。那怎么办呢?把库存表放在Redis(并发量单机10万)里面就好了。Redis 6.0之前只有一个线程可以访问(单线程模式),自动满足高并发模式。

评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值