lua脚本操作Redis

一次扣减一个商品库存

@Component

public class LuaDemo {

复制代码
@Autowired
private StringRedisTemplate redisTemplate;


public void test() {

  List<String> keys = new ArrayList<>();
    keys.add("yanjie007");

    String lua = "return redis.call('set',KEYS[1],ARGV[1])";

    RedisScript<String> redisScript=  RedisScript.of(lua,String.class);

    String shuai = stringRedisTemplate.execute(redisScript, keys, "今天真帅");

    System.out.println(shuai);

}

}

//扣减库存

@Test

void test2() throws IOException {

valueOperations.set(key,15L);

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 ");

sb.append(" else ");

sb.append(" return tonumber(redis_qty) "); // 0, 1,2,3 ...

sb.append(" end ");

sb.append(" ");

RedisScript script = RedisScript.of(sb.toString(),Long.class);

ExecutorService executorService = Executors.newCachedThreadPool();

复制代码
    for (int i = 1; i <= 10; i++) {
        int finalI = i;
        executorService.execute(()->{
            int needQty = RandomUtil.randomInt(1, 5);
            Long qty =  stringRedisTemplate.execute(script, CollUtil.newArrayList(key), needQty+"");
         if(qty.intValue() == -1 ){
             System.out.println("线程"+ finalI +"扣减成功,需求量是:"+needQty);
          } else {

             System.out.println("线程"+ finalI +"扣减失败,当前库存变量是:"+qty);
         }
        });
    }


    System.in.read();
}

一次扣减多个商品的库存

void test4() {

复制代码
    StringBuilder sb = new StringBuilder();
    sb.append(" local table = {}  "); // 你要扣减的key :product.1
    sb.append(" local values =  redis.call('mget',  unpack(KEYS) )"); // [product.1,product.2]   =>  product.1 product.2
    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] "); // product.1=23
    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> luaScript = RedisScript.of(sb.toString(), List.class);

      List<StockProduct> stockProducts =  new ArrayList<>();
      stockProducts.add(new StockProduct(5,1));
      stockProducts.add(new StockProduct(4,2));

    List<String> keys = stockProducts.stream().map(it -> "product." + it.getId()).collect(Collectors.toList());
    Object[] qtys = stockProducts.stream().map(it -> it.getQty() + "").toArray();
    List<String> list = stringRedisTemplate.execute(luaScript,
            keys,
            qtys);
    if(list.isEmpty()){
        System.out.println("库存冻结成功");
    } else {

        for (String key_qty : list) {
            String[] split = key_qty.split("=");
            System.out.println(split[0] + "库存不足,剩余库存量:" + split[1]);
        }

    }


    ThreadUtil.safeSleep(3000);


}
相关推荐
什么都想学的阿超10 分钟前
【Redis系列 03】掌握Redis编程艺术:事务、管道与Lua脚本完全指南
redis·junit·lua
想用offer打牌4 小时前
面试官问:Redis和MySQL数据一致,为什么还需要MySQL?🤠
数据库·redis·mysql
chen.@-@4 小时前
后端下载限速(redis记录实时并发,bucket4j动态限速)
数据库·redis·缓存
呼拉拉呼拉4 小时前
Redis高可用架构
数据库·redis·架构·高可用架构
编程乐学(Arfan开发工程师)5 小时前
42、响应处理-【源码分析】-浏览器与PostMan内容协商完全适配
java·spring boot·后端·测试工具·lua·postman
用户79117724235835 小时前
黑马点评【基于redis实现共享session登录】
java·redis
观无6 小时前
redis分布式锁
数据库·redis·分布式
颜淡慕潇6 小时前
Redis 实现分布式锁:深入剖析与最佳实践(含Java实现)
java·redis·分布式
CV点灯大师7 小时前
C++算法训练营 Day10 栈与队列(1)
c++·redis·算法
啾啾Fun7 小时前
【Java微服务组件】分布式协调P4-一文打通Redisson:从API实战到分布式锁核心源码剖析
java·redis·分布式·微服务·lua·redisson