Redis指令碼Lua實現訪問控制頻率
阿新 • • 發佈:2019-01-07
Redis 指令碼功能可以自定義新的命令,並且也是原子執行。
本篇和上一篇是相對應的。
一、簡單介紹下指令碼:
redis2.6推出指令碼功能,允許開發者使用 Lua語言編寫指令碼傳到Redis中執行,在Lua指令碼中可以呼叫大部分redis命令。
- 使用指令碼優點:
- 減少網路開銷:執行一次指令碼只需要傳送一次請求,減少網路往返時延。如果不使用指令碼,可能多個命令要傳送多個請求,還會出現競態情況。
- 原子操作:Redis會將指令碼作為一個整體執行,中間不會被其他事務插入。編寫指令碼過程中無須考慮競態條件,也無須使用事務。事務可以完成的所有功能都可以通過指令碼實現。
- 複用:客戶端傳送的指令碼會永久儲存在Redis 中,意味著其他客戶端可以複用這段指令碼。
二、使用指令碼實現訪問頻率限制,
- 方案一:
Lua程式碼如下:
-- Lua 使用 redis.call()呼叫redis命令
local times = redis.call('incr', KEYS[1])
if times == 1 then
-- KEYS[1] 鍵剛剛建立,所以為其設定生存時間
redis.call('expire', KEYS[1], ARGV[1])
end
if times > tonumber(ARGV[2]) then -- ARGV[2]為字串,需要轉為number
return 0
end
return 1
執行指令碼:
$ redis-cli –eval /path/to/ratelimiting.lua rate.limiting:127.0.0.1 , 10 3引數說明:
–eval:告訴redis-cli 讀取並執行後面的Lua指令碼。
/path/to/ratelimiting.lua : 檔案位置
rate.limiting:userId 要操作的key,在指令碼中用 KEYS[1]獲取
10 3 :兩個引數,在指令碼中用 ARGV[1]和ARGV[2] 獲取
注意:”,” 兩邊的空格不能省。
- 方案二:
Lua程式碼如下:
local limitLen = redis.call('llen', KEYS[1])
if limitLen < tonumber(ARGV[2]) then
redis.call('lpush', KEYS[1], os.time())
else
local times = redis.call('lindex', KEYS[1], -1)
if os.time() - times < ARGV[1] then
return 0
else
redis.call('lpush', KEYS[1], os.time())
redis.call('ltrim', KEYS[1], 0, ARGV[2])
end
end
return 1
執行指令碼:
$ redis-cli –eval /path/to/ratelimiting.lua rate.limiting:127.0.0.1 , 10 3rate.limiting:127.0.0.1 這個key 每10 秒最多訪問3次
如有錯誤,請留言指出。