1、場景
使用 redis 作為延遲隊列時,在 zrangebyscore
與 zrem
之間會存在 context switch
的情況,造成其他的消費者空轉
在其他場景下可能會發生更嚴重的情況
在掘金小冊《Redis 深度歷險:核心原理與應用實踐》第四章講的比較清楚,最后作者留了一個思考題
使用 Lua Scripting 來優化延時隊列的邏輯。
於是,我就用 redis 試了一下
2、編寫腳本
local value = redis.call("zrangebyscore", "delay-queue", 0, ARGV[1], "LIMIT", "0", "1")
if not value or not value[1] then
return nil
end
redis.log(redis.LOG_DEBUG, cjson.encode(value))
redis.call("zrem", "delay-queue", value[1])
return value[1]
-
腳本中執行 redis 命令可以使用 call 和 pcall ,區別是 call 遇見錯誤會拋出,pcall 會返回出來一個帶錯誤的 err
-
腳本的返回值會轉換成 redis 的回復返回給客戶端
-
腳本的參數會傳到 ARGV table 中
-
lua 的 index 從 1 開始
3、加載腳本
腳本我寫在了文件里面 popzset.lua
redis-cli -x script load < popzset.lua
加載腳本之后會返回一個摘要值
4、執行腳本
evalsha "520a9dd32adf29721b0d925e0fb338aa3c32ea66" {程序生成的時間}
5、參考資料
https://redisbook.readthedocs.io/en/latest/feature/scripting.html