Redis Lua scripting

Lua脚本

Redis从 2.6.0 版本开始内置 Lua 解释器,可以使用 EVAL 命令对 Lua 脚本进行求值。脚本是lua函数体内的代码,而不能是包括function关键字及大括号。脚本会以原子方式执行,当脚本运行时,其他任何客户端都不能执行命令,因此,脚本中代码不应该包含耗时操作。

语法:EVAL script numkeys key [key …] arg [arg …]。例如:

> eval "return {KEYS[1],KEYS[2],ARGV[1],ARGV[2]}" 2 key1 key2 first second
1) "key1"
2) "key2"
3) "first"
4) "second"

其中 "return {KEYS[1],KEYS[2],ARGV[1],ARGV[2]}" 是被求值的 Lua 脚本,数字 2 指定了键名参数的数量, key1key2 是键名参数,分别使用 KEYS[1]KEYS[2] 访问,而最后的 firstsecond 则是附加参数,可以通过 ARGV[1]ARGV[2] 访问它们。在脚本中调用Redis命令:

> eval "return redis.call('set',KEYS[1],'bar')" 1 foo
OK

在spring data redis中使用

实现一个简单的计数限流器。

@Configuration
public class RedisConfiguration {
	@Bean(name = "simpleRateLimitScript")
	public RedisScript<Boolean> script() {
		ClassPathResource resource = new ClassPathResource("META-INF/scripts/simple_rate_limiter.lua");
		return RedisScript.of(resource, Boolean.class);
	}
}
-- 在一段时间内(exp,秒),对某一操作(key),限制允许执行多少次(limit)。
local key = KEYS[1]
local limit = tonumber(KEYS[2])
local exp = tonumber(KEYS[3])
local currentLimit = tonumber(redis.call('GET', key) or 0)
if currentLimit + 1 > limit then
    return true
else
    redis.call("INCR", key)
    redis.call("EXPIRE", key, exp)
    return false
end
	private static final int MAX = 5;
	private static final int EXP_SECONDS = 10 * 60;
	public Boolean limit(String key) {
		List<String> keys = new ArrayList<>();
		keys.add("limit:" + key);
		keys.add(String.valueOf(MAX));
		keys.add(String.valueOf(EXP_SECONDS));
		return stringRedisTemplate.execute(countLimitScript, keys);
	}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章