数据库
首页 > 数据库> > Redis乐观锁解决超卖问题

Redis乐观锁解决超卖问题

作者:互联网

文章目录

Redis乐观锁解决超卖问题

情景假设:现在华为最新手机在做活动,双十二 00:00 准时前十名抢购的用户可以1元秒杀。而数据库对这个秒杀的动作呢,需要作出两个动作:
1、库存减1
2、记录秒杀成功的用户id
在这里插入图片描述
话不多说,我们直接用代码来演示:

这里直接给出控制器方法。

    @PostMapping("/secKill")
    public void TestSecKill(){
        /**
         *  实际开发,我们需要获取用户的id和商品的id
         *  这里作为学习使用,我们先写死
         */
        //用户id,我们使用随机数来表示每次访问的不同用户
        String userid = new Random().nextInt(50000) + "";
        //商品id,我们先写死
        String prodid = "1001";

        //1、连接redis(如果有设置requirepass的话,记得添加jedis.auth("你的密码");
        Jedis jedis = new Jedis("119.91.153.74", 6379);

        //2、拼接key
        String kcKey = "sk:"+prodid+":qt";  //库存key
        String userKey = "sk:"+userid+":user";  //秒杀成功用户key

        //使用乐观锁,监视库存
        jedis.watch(kcKey);

        //3、获取库存,为null表示活动未开始
        String kc = jedis.get(kcKey);
        if(kc == null){
            System.out.println("秒杀还未开始");
            jedis.close();
            return;
        }

        //4、判断用户是否重复秒杀
        if(jedis.sismember(userKey, userid)){
            System.out.println("您已成功秒杀,不可重复秒杀");
            jedis.close();
            return;
        }

        //5、库存小于等于0,秒杀结束
        if (Integer.parseInt(kc) <= 0){
            System.out.println("秒杀活动已结束,感谢您的参与");
            jedis.close();
            return;
        }

        //6、秒杀过程
        //开启事务
        Transaction transaction = jedis.multi();
        //组队
        //6.1 库存减1
        transaction.decr(kcKey);
        //6.2 添加秒杀成功用户
        transaction.sadd(userKey, userid);
        //执行
        List<Object> results = transaction.exec();
        //执行失败
        if (results == null || results.size() == 0){
            System.out.println("秒杀失败.....");
            jedis.close();
            return;
        }
        //执行成功
        System.out.println("恭喜您秒杀成功.......");
        jedis.close();
    }

然后我们来测试一下:
首先,先给redis添加库存:

set sk:1001:qt 10

然后我们使用ab工具模拟并发:
这里顺便介绍几个命令:

命令描述
-nrequests:请求次数
-cconcurrency:并发数
-Tcontent-type:用于POST和PUT请求,其值固定为’application/x-www-form-urlencoded’
-ppostfile:如果post请求有参数,要放到该文件中
-uputfile:如果put请求有参数,要放到该文件中

基本介绍就这么多,接下来我们直接用,使用命令:
注意:即使post请求没有参数,也要使用-p标签,否则好像会默认使用get请求,192.168.148.148是Tomcat服务器的ip地址(这里我的是我的windows的ip地址)。

ab -n 1000 -c 100 -p postfile -T ‘application/x-www-form-urlencoded’ http://192.168.148.148:8080/secKill

如果要查询自己本机的ip地址的话,在cmd下输入 ipconfig即可。它里面有一个Ipv4地址就是你的ip地址啦。

如果Linux服务器访问不了你的windows,那么我们也可以在windows上下载ab工具,并使用python来模拟我们的并发测试。

import os
#D:\Download\httpd-2.4.51-o111l-x64-vc15\Apache24\bin\ab是我们的ab工具路径
ab=os.popen(r'D:\Download\httpd-2.4.51-o111l-x64-vc15\Apache24\bin\ab -n 1000 -c 100 -p ./postfile -T application/x-www-form-urlencoded http://192.168.148.148:8080/secKill')
print(ab.read())

运行结果:(可以看到秒杀成功的次数是10次,成功解决了我们的超卖问题)
在这里插入图片描述
我们再去Redis下查看:
在这里插入图片描述
在这里插入图片描述

CentOS7下载ab工具

安装命令:

yum install httpd-tools

Windows下载ab工具

ab工具官网下载地址:https://www.apachehaus.com/cgi-bin/download.plx
进入后往下拉:
在这里插入图片描述
下载完成后直接解压即可。

标签:ab,Redis,System,乐观,jedis,close,println,秒杀,超卖
来源: https://blog.csdn.net/weixin_44741023/article/details/121539794