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变量读取方式