java - lua - redis 完成商品库存的删减

java调用lua脚本完成对商品库存的管理

主页链接 微风轻吟挽歌的主页

如若有帮助请帮忙点赞

java 复制代码
//lua脚本 获取到内存不够的商品
        StringBuilder sb = new StringBuilder();
        //定义一个数组存储可能缺少库存的值
        sb.append(" local  table = {} ");
        //获取值
        sb.append("  local values = redis.call('mget',unpack(KEYS)) ");
        //如果不够就放到table之中
        sb.append("  for i = 1, #KEYS do ");
        sb.append("     if tonumber(ARGV[i]) > tonumber(values[i]) then ");
        sb.append("         table[#table + 1] = KEYS[i] .. '=' .. values[i] ");
        sb.append("     end ");
        sb.append("  end");
        //判断 库存是否
        sb.append("  if #table > 0 then ");
        sb.append("  return table ");
        sb.append("  end ");

        sb.append("  for i = 1, #KEYS do  ");
        sb.append("  redis.call('decrby',KEYS[i],ARGV[i]) ");
        sb.append("  end ");
        sb.append("  return {} ");

lua 脚本的内容作业个简单的判断,相信逻辑大家都明白,只是lua脚本语言本身不太熟练,这里有一个简单模板,亲测可用 不一定时最优的模板

测试

这里的redisTemplate在官方jarbao中采用的jdk序列化方式导致中文乱码,我这里注入的是自己重写的(网上抄的),因为非本文重要内容,不再详述

java 复制代码
   @Autowired
    RedisTemplate<Object, Object> redisTemplate;

    @Resource(name = "redisTemplate")
     ValueOperations valueOperations;
    @Resource
    StringRedisTemplate stringRedisTemplate;

    @Test
        //通过lua脚本多线程操作库存
    void get() throws IOException {
        String key1  = "apple";
        String key2  = "banana";
        String key3  = "栗子";
        //三个商品并设置其库存量
        valueOperations.set(key1,15L);
        valueOperations.set(key2,8L);
        valueOperations.set(key3,6L);

        //lua脚本 获取到内存不够的商品
        StringBuilder sb = new StringBuilder();
        //定义一个数组存储可能缺少库存的值
        sb.append(" local  table = {} ");
        //获取值
        sb.append("  local values = redis.call('mget',unpack(KEYS)) ");
        //如果不够就放到table之中
        sb.append("  for i = 1, #KEYS do ");
        sb.append("     if tonumber(ARGV[i]) > tonumber(values[i]) then ");
        sb.append("         table[#table + 1] = KEYS[i] .. '=' .. values[i] ");
        sb.append("     end ");
        sb.append("  end");
        //判断 库存是否
        sb.append("  if #table > 0 then ");
        sb.append("  return table ");
        sb.append("  end ");

        sb.append("  for i = 1, #KEYS do  ");
        sb.append("  redis.call('decrby',KEYS[i],ARGV[i]) ");
        sb.append("  end ");
        sb.append("  return {} ");
        

        RedisScript<List> script = RedisScript.of(sb.toString(),List.class);
        ExecutorService executorService = Executors.newCachedThreadPool();
        for (int i = 0; i < 10; i++) {
            int i1 = RandomUtil.randomInt(1, 5);
            executorService.execute(()->{
                List execute = stringRedisTemplate.execute(script,
                        CollUtil.newArrayList(key1, key2, key3), String.valueOf(i1), String.valueOf(i1), String.valueOf(i1)
                );
                if(execute.isEmpty()){
                    System.out.println("库存足够,存储成功");
                    return;
                }
                for (Object obj : execute){
                    String[] split = obj.toString().split("=");
                    System.out.println(StrUtil.format("商品{} 需求量:{} 库存不足,仅剩{}",split[0],i1,split[1]));
                }
            });
        }
        //测试中执行所以需要阻塞使用防止因为多线程执行的时候因为其他线程走完导致的测试结束
        System.in.read();
    }

测试结果

ok,这次的lua脚本就记录完毕。

那么开始正事

相关推荐
热爱编程的小李7 分钟前
基于若以开发的新版情怀麻将后台
java
zhanghaha13142 小时前
HTML系列教程:14_HTML 表单与输入框 <form>、<input> 零基础详解
java·前端·javascript
yxlalm8 小时前
Spring AI+RAG 01-项目背景与技术选型
java·人工智能·spring
程序员清风8 小时前
Java 后端高并发设计:线程池、限流、熔断与降级
java·数据库·oracle
Seoyoneh9 小时前
Agentic Workflow编排架构:云客服从“被动响应”迈向“主动执行”的技术实现
java·开发语言·架构
海南java第二人9 小时前
对外 API 如何保证幂等性?插入数据 / 上传表格场景全方案汇总
java·幂等性
tryxr9 小时前
Chat2Excel 文件服务模块上传文件功能开发
java·项目·oss·easyexcel·文件服务
Tangyuewei9 小时前
Java 写 Agent:模型只是组件
java·开发语言
彧azz10 小时前
Java学习语法篇:变量
java·学习
x10n911 小时前
Postman 汉化完整指南
测试工具·lua·postman