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