Lua脚本

local key = 'cardPool.'..KEYS[1]..'-stock' -- redis中令牌桶对象的key
local initTokens = tonumber(KEYS[2]) -- {初始化时的库存数量}

local bucket = redis.call('hgetall', key) -- 当前 key 的令牌桶对象
local currentTokens -- 当前token数量
local runCount -- 累计运行次数统计

-- 若当前桶未初始化,先初始化令牌桶
if table.maxn(bucket) == 0 then
    -- 初始桶内令牌
    currentTokens = initTokens
    runCount = 0
elseif table.maxn(bucket) == 4 then
    currentTokens = tonumber(bucket[2])
    runCount = tonumber(bucket[4])
end

-- 如果当前桶内令牌小于 0,抛出异常
assert(currentTokens >= 0)

-- 如果当前令牌 == 0, 返回false
if currentTokens == 0 then
    redis.call('hset', key, 'tokensRemaining', currentTokens)
    redis.call('hset', key, 'runCount', runCount + 1)
    return false
else
    -- 如果当前令牌 大于 0, 更新当前桶内的令牌 -1, 返回true
    redis.call('hset', key, 'tokensRemaining', currentTokens - 1)
    redis.call('hset', key, 'runCount', runCount + 1)
    return true
end

JAVA运行Lua脚本:

		DefaultRedisScript<Boolean> redisScript = new DefaultRedisScript<>();
		redisScript.setScriptSource(new ResourceScriptSource(new ClassPathResource("lua/test.lua")));
		redisScript.setResultType(Boolean.class);

		Boolean result = true;
		long count = 0;
		do{
			Date _startTime = new Date();
			List<String> keys = Arrays.asList("pool1", "10000");
			try{
				result = redisTemplate.execute(redisScript, keys);
			}catch(Exception e){
				e.printStackTrace();
			}
			Date _endTime = new Date();
			long _timeCross = _endTime.getTime()- _startTime.getTime();
			count++;
			System.out.println("lua的第"+count+"次执行花了"+_timeCross+"毫秒");
		}while(result==true);

注意hgetall返回的redis变量读取方式