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();
    }
相关推荐
xrkhy2 小时前
canal1.1.8+mysql8.0+jdk17+redis的使用
android·redis·adb
MuYiLuck7 小时前
redis持久化与集群
java·数据库·redis
埃泽漫笔8 小时前
Redis性能优化避坑指南
redis
升鲜宝供应链及收银系统源代码服务8 小时前
升鲜宝生鲜配送供应链管理系统--- 《多语言商品查询优化方案(Redis + 翻译表 + 模糊匹配)》
java·数据库·redis·bootstrap·供应链系统·生鲜配送·生鲜配送源代码
JH30738 小时前
Redis 中被忽视的“键过期策略”与内存回收机制
数据库·redis·缓存
Microsoft Word8 小时前
Redis常见面试题
数据库·redis·缓存
bing.shao8 小时前
mongodb与redis在聊天场景中的选择
数据库·redis·mongodb
dudke8 小时前
c#实现redis的调用与基础类
数据库·redis·缓存
苦学编程的谢8 小时前
Redis_7_hash
数据库·redis·哈希算法
佛祖让我来巡山10 小时前
Redis实战终极指南:从客户端集成到性能优化,手把手教你避坑【第四部分】
redis·redis分布式锁实现·redis秒杀