乐观锁解决卖超问题

概述

卖超问题经常出现在高并发系统中,现在来一个demo吧

问题

首先建张表,stock

id	bigint	
product_id	bigint	
count	int	
version	int	

接着创建一个没有乐观锁的扣减库存的问题,我们会用Jmeter来模拟多线程请求接口来展现超卖问题,接着看

超卖代码

Controller,重点注意iStockService.updateStock(productId,null);

updateStock第二个参数为,version,版本控制,这也是乐观锁的实现方式


@PostMapping
    public String reduceStock(@RequestParam Long productId){

        Stock one = iStockService.getOne(new QueryWrapper<Stock>().lambda().eq(Stock::getProductId, productId));

        log.info("stock_num:"+one.getCount());

        if (one.getCount() > 0){
            boolean successOrNot = iStockService.updateStock(productId,null);
            return successOrNot ? "good" : "fail";
        }

        return null;
    }

service

@Service
public class StockServiceImpl extends ServiceImpl<StockMapper, Stock> implements IStockService {

    @Autowired
    private StockMapper stockMapper;

    @Override
    public boolean updateStock(Long productId, Integer version) {
        return stockMapper.updateStock(productId,version);
    }
}

mapper

public interface StockMapper extends BaseMapper<Stock> {

    boolean updateStock(@Param("productId") Long productId,@Param("version") Integer version);
}

xml

>
        UPDATE stock SET count = count - 1,version = version + 1
        >
            != null and productId !=''">
                and product_id = #{productId}
            >
            != null">
                and version = #{version}
            >
        >
    >

好了所有的代码,接着先来看看jmeter的使用,然后开始测试

jmeter的使用

在正式贴超卖代码前,先来看看jmeter的基本使用

用来测试的是5.4.3版本,各位可以参考
下载地址

在jmeter的bin目录下找到jemeter.properties,打开jmeter.properties,找到language选项,设定为zh_CN

language=zh_CN

打开就可以看到是中文的了

吐槽一下,CSDN的图片都不能上传,是真的坑,展示只能用中文?什么鬼…考虑换个博客了,神坑

然后测试计划右键添加–>线程(用户)–>线程组

在线程数那设置100左右的线程,循环次数1,Ramp-Up 1
线程组那,右键添加–>取样器–>HTTP请求

在Http请求基本那做Web服务器的,协议、IP、端口号、路径、参数等地方做相应设置

如有参数,在参数底部选择添加填入参数名、参数值即可启动

在线程组处,添加–>监听器–>观察结果树,好的所有配置已完成,让我们开始测试

测试

2022-06-12 12:54:55.493  INFO 7380 --- [io-8021-exec-48] ho.controller.StockController            : stock_num:-34
2022-06-12 12:54:55.493  INFO 7380 --- [io-8021-exec-49] ho.controller.StockController            : stock_num:-36
2022-06-12 12:54:55.493  INFO 7380 --- [io-8021-exec-29] ho.controller.StockController            : stock_num:-36

接着可以看到,库存数量为负的了,也就是卖超了,所以怎么办呐?

乐观锁解决卖超

来看看解决方案把,

给version一个默认值(数据库中设置),并且将version传到mapper中,如下

iStockService.updateStock(productId,one.getVersion());

@PostMapping
    public String reduceStock(@RequestParam Long productId){

        Stock one = iStockService.getOne(new QueryWrapper<Stock>().lambda().eq(Stock::getProductId, productId));

        log.info("stock_num:"+one.getCount());

        if (one.getCount() > 0){
            boolean successOrNot = iStockService.updateStock(productId,one.getVersion());
            return successOrNot ? "good" : "fail";
        }

        return null;
    }

可以再看看,从输出中可以看到,没有问题了,这就是用乐观锁,卖超问题的解决方案

2022-06-12 13:09:03.827  INFO 2460 --- [io-8021-exec-19] ho.controller.StockController            : stock_num:10
2022-06-12 13:09:03.852  INFO 2460 --- [io-8021-exec-10] ho.controller.StockController            : stock_num:9
2022-06-12 13:09:03.868  INFO 2460 --- [nio-8021-exec-1] ho.controller.StockController            : stock_num:8
2022-06-12 13:09:03.905  INFO 2460 --- [io-8021-exec-31] ho.controller.StockController            : stock_num:7
2022-06-12 13:09:03.913  INFO 2460 --- [nio-8021-exec-9] ho.controller.StockController            : stock_num:6
2022-06-12 13:09:03.929  INFO 2460 --- [nio-8021-exec-2] ho.controller.StockController            : stock_num:5
2022-06-12 13:09:03.945  INFO 2460 --- [nio-8021-exec-6] ho.controller.StockController            : stock_num:4
2022-06-12 13:09:03.977  INFO 2460 --- [io-8021-exec-14] ho.controller.StockController            : stock_num:3
2022-06-12 13:09:03.991  INFO 2460 --- [io-8021-exec-28] ho.controller.StockController            : stock_num:2
2022-06-12 13:09:04.006  INFO 2460 --- [io-8021-exec-15] ho.controller.StockController            : stock_num:1
2022-06-12 13:09:04.037  INFO 2460 --- [io-8021-exec-30] ho.controller.StockController            : stock_num:0
2022-06-12 13:09:04.061  INFO 2460 --- [io-8021-exec-23] ho.controller.StockController            : stock_num:0

你可能感兴趣的:(多线程,java,压力测试,开发语言)