Lua脚本操作redis

模拟库存扣减

基础版

java 复制代码
@SpringBootTest
class LuaTests {


    @Resource(name="redisTemplate")
    ValueOperations<String,Long> valueOperations;

    @Autowired
    StringRedisTemplate stringRedisTemplate;

    final  String priductKey = "product.1";


    @Test
    void test1() throws IOException {
        StringBuilder sb = new StringBuilder();
        sb.append(" local key = KEYS[1] ");
        sb.append(" local qty = ARGV[1] ");
        sb.append(" local redis_qty = redis.call('get',key) ");
        sb.append(" if tonumber(redis_qty) >= tonumber(qty)  then ");
        sb.append("   redis.call('decrby',key,qty) ");
        sb.append("  return  -1 "); // -1 代表的扣减成功了
        sb.append(" else ");
        sb.append("  return tonumber(redis_qty)  "); //返回的当前的库存量 , 0,1,2 .......
        sb.append(" end ");
        RedisScript<Long>  script =  RedisScript.of(sb.toString(),Long.class);

        ExecutorService executorService = Executors.newCachedThreadPool();
        for (int i = 0; i < 10; i++) {
            executorService.execute(()->{
               int needQty = RandomUtil.randomInt(1,5);
                Long qty = stringRedisTemplate.execute(script, CollUtil.newArrayList(priductKey), needQty + "");
                if(qty == -1 ){
                    System.out.println(StrUtil.format("{} 扣减成功,需求量是:{}",Thread.currentThread().getId(),needQty));
                } else {
                    System.out.println(StrUtil.format("{} 扣减失败,您的需求量是:{},当前库存量是:{}",Thread.currentThread().getId(),needQty,qty));
                }
            });

        }

     System.in.read();
    }

升级版

java 复制代码
@Test
    void test2() throws IOException {
        final String key1 = "product.1";
        final String key2 = "product.2";
        final String key3 = "product.3";
        valueOperations.set(key1,5l);
        valueOperations.set(key2,10l);
        valueOperations.set(key3,15l);
        StringBuilder sb = new StringBuilder();
        sb.append(" local table = {} ");
        sb.append(" local redis_qtys =  redis.call('mget',unpack(KEYS)) ");
        sb.append(" for i=1, #KEYS do ");
        sb.append("  if  tonumber(ARGV[i]) >  tonumber(redis_qtys[i]) then");
        sb.append("   table[#table + 1] = KEYS[i] .. '=' .. redis_qtys[i]  "); // product.2=56
        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 < 1; i++) {
            executorService.execute(()->{
                int needQty1 = RandomUtil.randomInt(1,7);
                int needQty2 = RandomUtil.randomInt(1,10);
                int needQty3 = RandomUtil.randomInt(1,16);
                List ret = stringRedisTemplate.execute(script, CollUtil.newArrayList(key1,key2,key3), needQty1+"",needQty2+"",needQty3+"");
                if(ret.size() == 0 ){
                    System.out.println(StrUtil.format("{} 扣减成功,需求量是:{},{},{}",Thread.currentThread().getId(),needQty1,needQty2,needQty3));
                } else {

                    System.out.println(StrUtil.format("{} 扣减失败,您的需求量是:{},{},{} ",Thread.currentThread().getId(),needQty1,needQty2,needQty3));
                   for(Object obj :ret){
                       System.out.println(obj);
                   }
                }
            });

        }

        System.in.read();
    }
相关推荐
yurenpai(27届找实习中)23 分钟前
redis_点评(25.附件店铺—把数据库里的店铺按【类型分组】,批量导入Redis 的 GEO 地理位置结构)
java·redis·缓存
闪电悠米1 小时前
黑马点评-优惠券秒杀-05_local_lock_cluster_problem
java·spring boot·redis·缓存
西安邮电大学2 小时前
Redis为什么快?
java·redis·后端·其他·面试
稚枭天卓2 小时前
mac 安装 redis
redis·macos
yurenpai(27届找实习中)3 小时前
redis_点评(26.附近店铺——实现附近商家功能)
数据库·spring boot·redis
不剪发的Tony老师3 小时前
RedisME:一个现代化、轻量级Redis管理工具
数据库·redis
消失的旧时光-19433 小时前
企业认证与安全体系(四):企业登录认证流程全解析——JWT、Redis、Spring Security 如何协同工作?
redis·安全·spring·spring security·jwt
愤怒的苹果ext3 小时前
Spring Boot Redis Stream队列
spring boot·redis·消息队列·stream
MageGojo4 小时前
短链还原 API 怎么接入:展开跳转链路、查看状态码和最终落地页
数据库·redis·缓存
我是一颗柠檬4 小时前
【Redis】字符串与哈希Day3(2026年)
数据库·redis·后端·database