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);
	}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章