LUA脚本使用

1、定义LUA脚本

/**
     * 扣减库存Lua脚本
     * 库存(stock)-1:表示不限库存
     * 库存(stock)0:表示没有库存
     * 库存(stock)大于0:表示剩余库存
     * <p>
     * 库存key
     * -3:库存未初始化
     * -2:库存不足
     * -1:不限库存
     * 大于等于0:剩余库存(扣减之后剩余的库存)
     * redis缓存的库存(value)是-1表示不限库存,直接返回1
     */
public static final String DEDUCT_STOCK_LUA =
            "if (redis.call('exists', KEYS[1]) == 1) then" +
                    "       local stock = tonumber(redis.call('get', KEYS[1]));" +
                    "       local num = tonumber(ARGV[1]);" +
                    "       if (stock == -1) then" +
                    "           return -1;" +
                    "       end;" +
                    "       if (stock >= num) then" +
                    "           return redis.call('incrby', KEYS[1], 0 - num);" +
                    "       end;" +
                    "       return -2;" +
                    "   end;" +
                    "   return -3;";

通过分析以上lua脚本,可以看出脚本的执行流程。

第一步:判断了一下KEYS[1]是否存在,不存在则返回-3,-3标识库存未初始化;

第二步:KEYS[1]值存在,则获取到KEYS[1]的值stock,即库存数量,在获取到ARGV[1],将其转化为数字;

第三步:判断一下stock库存数量是否是-1,-1表示不限制库存数量;

第四步:如果库存数量不为-1,那么就判断下stock库存数量是否是大于等于要扣减的库存数,如果大于等于,表示库存是充足的可以进行扣减操作,然后返回扣减后当前库存数量;

第五步:如果小于0,则库存不足,不能扣减,此时返回-2,表示库存不足。

在lua脚本中,包含了KEYS[1]与ARGV[1],分别代表两个入参,一个是操作的key,一个是操作的变量值(库存扣减数量)。

/**
     * 修改库存数量
     * 如果缓存存在,则获取库存数量与修改数量
     * <p>
     * 1、如果修改数量大于0,则增加库存数量
     * 2、如果修改数量小于0,则扣减库存
     * 2.1、库存数量大于扣减的数量,则直接扣减
     * 2.2、库存数量小于扣减的数量,则库存不足,将库存置为0
     */
    public static final String UPDATE_STOCK_LUA =
            "if (redis.call('exists', KEYS[1]) == 1) then" +
                    "       local stock = tonumber(redis.call('get', KEYS[1]));" +
                    "       local num = tonumber(ARGV[1]);" +
                    "       if (num > 0) then" +
                    "           return redis.call('incrby', KEYS[1], num);" +
                    "       end;" +
                    "       if (num < 0 and stock >= -num) then" +
                    "           return redis.call('incrby', KEYS[1], num);" +
                    "       end;" +
                    "       if (num < 0 and stock < -num) then" +
                    "           return redis.call('incrby', KEYS[1], 0 - stock);" +
                    "       end;" +
                    "       return -2;" +
                    "   end;" +
                    "   return -3;";

2、使用LUA脚本

private Long deductStock(String key, int num) {
        // 脚本里的KEYS参数
        List<String> keys = new ArrayList<String>();
        keys.add(key);
        // 脚本里的ARGV参数
        List<String> args = new ArrayList<String>();
        args.add(Integer.toString(num));

        // 将sha保存到Redis中缓存起来
        String sha = redisClient.get(LuaScriptEnum.DEDUCT_STOCK_LUA.getKey());
        if (StringUtils.isEmpty(sha)) {
            sha = redisClient.scriptLoad(LuaScriptEnum.DEDUCT_STOCK_LUA.getScript());
            redisClient.set(LuaScriptEnum.DEDUCT_STOCK_LUA.getKey(), sha);
            redisClient.expire(LuaScriptEnum.DEDUCT_STOCK_LUA.getKey(), 7, TimeUnit.DAYS);
        }
        Object result = redisClient.evalsha(sha, keys, args, false);
        if (result != null) {
            return Long.valueOf(String.valueOf(result));
        }
        log.error("扣减库存返回值为空");
        return 0L;
    }
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值