Redis+Lua实现简易的秒杀抢购

1 商品抢购

主要逻辑是:减库存,记录抢购成功的用户

@RestController
public class DemoController {

    @Resource
    private StringRedisTemplate stringRedisTemplate;

    private static final String GOODS_STOCK_KEY = "goods:001";  //  秒杀商品库存
    private static final String GOODS_USER_KEY = "users:001";   //  抢购成功的用户列表

    /**
     * 在不加锁的情况下,会发生超卖
     */
    @GetMapping("/seckill")
    public String seckill() {
        int userId = (int) (Math.random() * 1000);

        ValueOperations valueOps = stringRedisTemplate.opsForValue();
        ListOperations listOps = stringRedisTemplate.opsForList();

        int stock = Integer.parseInt(valueOps.get(GOODS_STOCK_KEY));

        if (stock > 0) {
            valueOps.decrement(GOODS_STOCK_KEY);
            listOps.leftPush(GOODS_USER_KEY, String.valueOf(userId));
            return "抢购成功";
        } else {
            return "商品已售罄";
        }
    }

    /**
     * 将多个命令打包成一个原子操作,利用redis单线程执行命令的特性,在不加锁的情况下避免了资源竞争
     */
    @GetMapping("/seckill_lua")
    public String seckill_lua() {
        int userId = (int) (Math.random() * 1000);

        String script = "if tonumber(redis.call('get', KEYS[1])) > 0 then " +
                "redis.call('decr', KEYS[1]); " +
                "redis.call('lpush', KEYS[2], ARGV[1]); " +
                "return 1; " +
                "else " +
                "return 0; " +
                "end; ";

        DefaultRedisScript redisScript = new DefaultRedisScript();
        redisScript.setResultType(Long.class);
        redisScript.setScriptText(script);

        List keyList = Arrays.asList(GOODS_STOCK_KEY, GOODS_USER_KEY);

        Long result = stringRedisTemplate.execute(redisScript, keyList, String.valueOf(userId));

        if (result == 1) {
            return "抢购成功";
        } else {
            return "商品已售罄";
        }
    }
}

对比两次的结果:

Redis+Lua实现简易的秒杀抢购

2 多线程处理Excel导入

/**
 * 多线程处理Excel导入
 *
 * PS:
 *  Executors返回的线程池对象的弊端如下:
 *  (1) FixedThreadPool和SingleThreadPool: 允许的请求队列长度为Integer.MAX_VALUE,可能会堆积大量的请求,从而导致OOM。
 *  (2) CachedThreadPool: 允许的创建线程数量为Integer.MAX_VALUE,可能会创建大量的线程,从而导致OOM。
 */
@PostMapping
public void excelImport() throws InterruptedException {
    //  待处理的数据(比如:从Excel中读取的数据)
    List dataList = new ArrayList();

    //  多线程处理
    ExecutorService executorService = Executors.newFixedThreadPool(5);
    CountDownLatch countDownLatch = new CountDownLatch(dataList.size());
    for (Object obj : dataList) {
        executorService.submit(new Runnable() {
            @Override
            public void run() {
                try {

                } catch (Exception ex) {

                } finally {
                   countDownLatch.countDown();
                }
            }
        });
    }

    countDownLatch.await(30, TimeUnit.SECONDS);

    //  后续执行

    //  返回结果
}

Original: https://www.cnblogs.com/cjsblog/p/16438567.html
Author: 废物大师兄
Title: Redis+Lua实现简易的秒杀抢购

原创文章受到原创版权保护。转载请注明出处:https://www.johngo689.com/612190/

转载文章受原作者版权保护。转载请注明原作者出处!

(0)

大家都在看

  • IntelliJ IDEA community 安装教程

    jetbrains官网下载 IntelliJ IDEA安装包 此处选择社区版的zip文件 下载完成后解压安装包,此处解压目录为 E:\IntelliJ IDEA\ 开始安装首先添加…

    数据库 2023年6月11日
    0139
  • MySQL Operator 01 | 架构设计概览

    高日耀 资深数据库内核研发毕业于华中科技大学,喜欢研究主流数据库架构和源码,并长期从事分布式数据库内核研发。曾参与分布式 MPP 数据库 CirroData 内核开发(东方国信),…

    数据库 2023年5月24日
    0162
  • 内嵌h5调试神器-vConsole

    vConsole 一个轻量、可拓展、针对手机网页的前端开发者调试面板,可用于APP内嵌H5及其他调试H5的地方。 使用 方法一:cdn 方式引入 // 引入 // 初始化 var …

    数据库 2023年6月11日
    0119
  • MyBatis(三)-动态SQL

    1、if 注意:test里面使用的参数,可以是mybatis的默认参数,也可以是实体属性名,但是不能是没有指定别名的参数名(尤其是单个参数,也必须起别名,否则异常); 单独使用if…

    数据库 2023年6月16日
    0138
  • LeetCode 9. 回文数

    题目 题目链接:https://leetcode.cn/problems/palindrome-number/ 给你一个整数x,如果x是一个回文整数,返回true;否则,返回fal…

    数据库 2023年6月11日
    0157
  • leetcode 513. Find Bottom Left Tree Value 找树左下角的值 (简单)

    给定一个二叉树的 根节点 root,请找出该二叉树的 最底层 最左边 节点的值。 假设二叉树中至少有一个节点。 示例 1: 输入: root = [2,1,3]输出: 1 示例 2…

    数据库 2023年6月16日
    0152
  • 6、发送验证码功能(Redis)

    一、业务需求: 1、后端随机生成短信验证码,并在服务器端保存一定时间(redis); 2、将短信验证码发给用户; 3、用户输入短信验证码提交后,在后端与之前生成的短信验证码作比较,…

    数据库 2023年6月6日
    0137
  • myrocks复制中断问题排查

    mysql可以支持多种不同的存储引擎,innodb由于其高效的读写性能,并且支持事务特性,使得它成为mysql存储引擎的代名词,使用非常广泛。随着SSD逐渐普及,硬件存储成本越来越…

    数据库 2023年6月9日
    0154
  • 记一次生产事故,Redis内存问题排查与解决

    前几天生产的Redis突然挂掉了,之前都没有太注意过Redis那边的使用情况,这次Redis挂掉重启后,发现在那台服务器上,Redis占用了足足30G的运行内存,这才意识到Redi…

    数据库 2023年6月6日
    0142
  • 一段文字

    https://book.douban.com/review/13674387/现代人的困境,其实从出生开始每个人都有强烈的感受。我们会按户口管理,强调身份的是各种标签,各种统计数…

    数据库 2023年6月11日
    0116
  • 10、比较Bigdecimal类型是否相等的方法

    一、Bigdecimal.equals()详解: Bigdecimal的equals方法不仅仅比较值的大小是否相等,首先比较的是scale(scale是bigdecimal的保留小…

    数据库 2023年6月6日
    0156
  • tomcat加载启动过程

    流程图 posted @2022-08-19 17:43 默念x 阅读(9 ) 评论() 编辑 Original: https://www.cnblogs.com/monianxd…

    数据库 2023年6月16日
    0142
  • 9 &和&&的区别

    &运算符有两种用法 在解释按位与&之前,我们先了解一个知识:程序中的所有数在计算机内存中都是以二进制的形式存储的,位运算就是直接对内存中整数的二进制位进行操作。 按…

    数据库 2023年6月6日
    0162
  • ansible-复制模块

    简介:临时的,在ansible中是指需要快速执行的单条命令,并且不需要保存的命令。对于复杂的命令则为 playbook。 1、复制模块 可在终端执行ansible-doc copy…

    数据库 2023年6月14日
    0137
  • Mysql查询优化

    mysq查询l优化 指标:执行时间 检查的行数 返回的行数 explain关键字 — 实际SQL,查找用户名为Jefabc的员工 select * from emp where …

    数据库 2023年5月24日
    0165
  • HTTP Study

    定义:在两点之间传输文本,视频,图片等超文本数据的协议和规范 HTTP风险 通信使用明文,https通过信息加密(混合加密)解决 无法验证报文的完整性,https通过校验机制(摘要…

    数据库 2023年6月16日
    0123
亲爱的 Coder【最近整理,可免费获取】👉 最新必读书单  | 👏 面试题下载  | 🌎 免费的AI知识星球