LUA脚本使用

1、定义LUA脚本

/**
     * 扣减库存Lua脚本
     * 库存(stock)-1:表示不限库存
     * 库存(stock)0:表示没有库存
     * 库存(stock)大于0:表示剩余库存
     * 

* 库存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,一个是操作的变量值(库存扣减数量)。

/**
     * 修改库存数量
     * 如果缓存存在,则获取库存数量与修改数量
     * 

* 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 keys = new ArrayList();
        keys.add(key);
        // 脚本里的ARGV参数
        List args = new ArrayList();
        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;
    }

你可能感兴趣的:(lua,redis,开发语言)