当前位置: 首页 > news >正文

使用redis+lua通过原子减解决超卖问题【示例】

系列文章目录

一、SpringBoot连接MySQL数据库实例【tk.mybatis连接mysql数据库】
二、SpringBoot连接Redis与Redisson【代码】
三、SpringBoot整合WebSocket【代码】
四、使用redis+lua通过原子减解决超卖问题【示例】
五、SpringBoot整合Elasticsearch【代码示例】

文章目录

  • 系列文章目录
  • 前言
  • 一、准备工作
  • 二、不使用Lua
  • 三、使用Lua


前言

超卖,即在并发的情况下,所售商品数量大于商品的库存数量。在并发量大的情况下,用户请求同时到达,对数据库进行操作,在没有采取相应的处理的情况时从而导致出现超卖现象。

一、准备工作

在redis中放入十件商品

在这里插入图片描述


二、不使用Lua

使用20个线程抢商品

public void test () {ExecutorService service = Executors.newFixedThreadPool(20);for (int i = 0; i < 20; i++) {int finalI = i;service.execute(new Runnable() {@Overridepublic void run() {if (Integer.parseInt(String.valueOf(redisUtils.get("test"))) > 0) {int execute = Integer.parseInt(String.valueOf(redisUtils.decr("test", 1)));if (execute != 0) {log.info("线程" + finalI + "抢到了商品!!!");} else {log.info("线程" + finalI + "未抢到商品");}} else {log.info("商品数量不足");}}});}
}

在这里插入图片描述
运行代码发现已经超出了十个人抢到了商品。
此时redis的存值已经变为了负数,出现了超卖的情况。

在这里插入图片描述


三、使用Lua

public void test_lua () {StringBuilder sb = new StringBuilder();sb.append("if (redis.call('exists', KEYS[1]) == 1) then");    // 判断key是否存在sb.append("    local stock = tonumber(redis.call('get', KEYS[1]));");   // 获取锁sb.append("    if (stock == -1) then");sb.append("        return 1;");sb.append("    end;");sb.append("    if (stock > 0) then");sb.append("        redis.call('decrby', KEYS[1], 1);");    // 商品数量减1sb.append("        return stock;");sb.append("    end;");sb.append("    return 0;");sb.append("end;");sb.append("return -1;");String STOCK_LUA = sb.toString();DefaultRedisScript<Long> objectDefaultRedisScript = new DefaultRedisScript<>();objectDefaultRedisScript.setScriptText(STOCK_LUA);objectDefaultRedisScript.setResultType(Long.class);ArrayList<String> keys = new ArrayList<>();     // 脚本中的KEYS参数keys.add("test");ExecutorService service = Executors.newFixedThreadPool(20);for (int i = 0; i < 20; i++) {int finalI = i;service.execute(new Runnable() {@Overridepublic void run() {int execute = Integer.parseInt(redisTemplate.execute(objectDefaultRedisScript, keys).toString());if (execute != 0) {log.info("线程" + finalI + "抢到了商品!!!");} else {log.info("线程" + finalI + "未抢到商品");}}});}
}

依然使用20个线程抢商品,运行代码只有10个线程抢到了商品
在这里插入图片描述
此时redis中的存值为0
在这里插入图片描述

http://www.lryc.cn/news/168644.html

相关文章:

  • WebFlux异常处理:onErrorReturn和onErrorResume
  • 《动手学深度学习 Pytorch版》 4.5 权重衰减
  • 数据脱敏的风险量化评估介绍
  • SpringCloudGateway网关实战(三)
  • 08在MyBatis-Plus中配置多数据源
  • Centos8安装docker并配置Kali Linux图形化界面
  • 游戏开发初等数学基础
  • svg图片代码data:image/svg+xml转png图片方法
  • 解决问题:Replace `‘vue‘;⏎` with `“vue“;`
  • ThinkPHP 5.0通过composer升级到5.1,超级简单
  • 计算机竞赛 多目标跟踪算法 实时检测 - opencv 深度学习 机器视觉
  • 一文了解大模型工作原理——以ChatGPT为例
  • CPP-Templates-2nd--第十九章 萃取的实现 19.7---
  • python 采用selenium+cookies 获取登录后的网页
  • 【测试开发】答疑篇 · 什么是软件测试
  • 深入解析顺序表:揭开数据结构的奥秘,掌握顺序表的精髓
  • 数据风险量化评估方案
  • EasyAVFilter代码示例之将视频点播文件转码成HLS(m3u8+ts)视频点播格式
  • day-50 代码随想录算法训练营(19)动态规划 part 11
  • 自定义权限指令与防止连点指令
  • UE5、CesiumForUnreal实现瓦片坐标信息图层效果
  • PostgreSQL执行计划
  • 【2023 睿思芯科 笔试题】~ 题目及参考答案
  • Java手写AVL树
  • 运维自动化:提高效率的秘诀
  • C++设计模式_05_Observer 观察者模式
  • github网站打不开,hosts文件配置
  • 总结PCB设计的经验
  • HCIE-HCS规划设计搭建
  • c语言输出杨辉三角