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();
    }
相关推荐
Y编程小白31 分钟前
Redis可视化工具--RedisDesktopManager的安装
数据库·redis·缓存
东软吴彦祖3 小时前
包安装利用 LNMP 实现 phpMyAdmin 的负载均衡并利用Redis实现会话保持nginx
linux·redis·mysql·nginx·缓存·负载均衡
DZSpace5 小时前
使用 Helm 安装 Redis 集群
数据库·redis·缓存
github_czy10 小时前
(k8s)k8s部署mysql与redis(无坑版)
redis·容器·kubernetes
等一场春雨16 小时前
CentOS 安装Redis
linux·redis·centos
qw94918 小时前
Spring 6 第6章——单元测试:Junit
spring·junit·单元测试
天天向上杰19 小时前
简识Redis 持久化相关的 “Everysec“ 策略
数据库·redis·缓存
清风-云烟20 小时前
使用redis-cli命令实现redis crud操作
java·linux·数据库·redis·spring·缓存·1024程序员节
draymond710721 小时前
redis-redission的加锁源码与看门狗机制
redis
vd_vd21 小时前
Redis内存面试与分析
数据库·redis·面试