【分布式锁通关指南 01】从解决库存超卖开始加锁的初体验

引言

在电商业务中,库存超卖问题就如同一颗定时炸弹,随时可能在高并发的环境下引爆。对于后端工程师来说,就需要为这颗炸弹加上防止爆炸的枷锁,从而避免因为超卖导致的资损问题。本系列文章就将从这个场景入手,一步步地为各位读者引入分布式锁的各种实现,从而让大家可以掌握分布式锁在常见场景的使用。

需求背景

背景非常简单,就是在电商项目中,用户购买商品和数量后后,系统会对商品的库存进行相应数量的扣减。因此,我们模拟这个场景就需要商品表库存表两张表,但业务并不是这里的重点,需要简化一下,一张简单的商品库存表足以,如下:

 

sql

代码解读

复制代码

CREATE TABLE `tb_goods_stock` ( `id` bigint(20) NOT NULL AUTO_INCREMENT COMMENT '主键id', `goods_id` bigint(20) NOT NULL COMMENT '商品id', `stock` int NOT NULL COMMENT '库存数', PRIMARY KEY (`id`) ) COMMENT = '商品库存表';

接着,我们创建一个SpringBoot的项目,在接口中实现简单的扣减库存的逻辑,示例如下:

 

java

代码解读

复制代码

public String deductStock(Long goodsId,Integer count){ //1.查询商品库存的库存数量 Integer stock = stockDao.selectStockByGoodsId(goodsId); //2.判断商品的库存数量是否足够 if (stock < count) return "库存不足"; //3.如果足够,扣减库存数量 stockDao.updateStockByGoodsId(goodsId,stock-count); //4.返回扣减成功 return "库存扣减成功!"; }

创建成功后,先往数据库里插入一条商品id为1、库存为1的数据,便于我们测试接口的逻辑。分别执行两次调用,分别得到库存不足库存扣减成功的提示,验证逻辑没有问题,如下:

 

发现问题

上面的例子如果是通过单词访问,那么它的执行结果也是符合我们预期的。但在高并发场景下,多个线程同时访问同一个数据就可能出现超卖问题。因此,我们用JMeter来模拟大量并发数据来进行线上抢购场景复现,如下:

 添加一个线程组,设定50个线程和100次循环次数,如下:

 这时再将数据库里的商品id为1的数据的库存修改为5000,如下:

接着执行HTTP请求,如下:

 通过聚合报告可以看出5000次请求都执行成功,这个时候按照正常逻辑,库存应该扣完了,回到数据库查询,如下:

通过查询发现还有4000多个库存,带换到线上场景,这个时候后续还有用户继续请求购买,最终实际卖出的肯定会远远超过库存,这就是经典的超卖问题

JVM锁初显神通

并发问题去找锁这个几乎是大家的共识,那么这里的超卖问题也不例外。因此,最直接的办法就是直接在涉及扣减库存的逻辑或操作上进行加锁处理。首先,最先想到的就是JVM锁,只需要一个synchronized关键字就可以实现,代码修改如下:

 

java

代码解读

复制代码

public synchronized String deductStock(Long goodsId,Integer count){ //1.查询商品库存的库存数量 Integer stock = stockDao.selectStockByGoodsId(goodsId); //2.判断商品的库存数量是否足够 if (stock < count) return "库存不足"; //3.如果足够,扣减库存数量 stockDao.updateStockByGoodsId(goodsId,stock-count); //4.返回扣减成功 return "库存扣减成功!"; }

我们这时候去把数据库的库存还原下,然后重新用JMeter进行请求(Ps:原参数不变),执行后我们先看数据库结果,如下:

 可以看到这次的库存就被扣减完了,但我们查看聚合报告会发现对比前面的请求,有一项指标下降了很多-吞吐量,从三千多到现在的一千多,所以加锁肯定对性能是会

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值