背景說明
使用Redis
開發分佈式應用時,難免會遇到需要使用分佈式鎖來確保某一小段邏輯的原子性操作,如:當存在某個key
對應的值A
大於值B
時,則返回false
;否則A + 1
。試想一下,如果用到分佈式鎖,是不是有點感覺像是殺雞用宰牛刀?
由於Redis
的操作都是原子性的,所以我們可以將如上所述的類似邏輯採用Lua
腳本表述作爲一個原子任務向redisClient
提交,可以避免採用分佈式鎖。如腳本:
local key = KEYS[1]
local expire_time = tonumber(ARGV[1])
local max_count = tonumber(ARGV[2])
-- 驗證key是否存在,不存在設置過期時間
local is_key_exists = redis.call("EXISTS", key)
-- 存在
if is_key_exists == 1 then
local key_count = redis.call("get", key)
if tonumber(key_count) >= max_count then
return false;
else
redis.call("incr", key)
return true;
end
else
redis.call("incr", key);
redis.call("expire", key, expire_time)
return true;
end
但此時發現,在Redis
中調試是個困難的事情。但幸好,從Redis 3,2
版本開始,提供了Lua script debugger
來解決此問題。
Redis Lua調試器特點
Redis Lua
調試器代號爲LDB
,特點如下:
- 支持單步調試
- 支持靜態和動態斷點
- 支持將被調試的腳本載入至調試終端
- 支持對
Lua
變量進行觀察 - 支持追蹤腳本執行的
Redis
命令 - 支持以美觀方式打印
Redis
值及Lua
值 - 能夠在無線循環及長時間執行步驟中模擬出斷點
- 採用
CS
模型,S
即Redis
服務器,C
即redis-cli
客戶端 - 默認情況下,每個調試會話都是
fork
子進程進行的。所以調試過程中不會影響Redis
其他操作;調試結束後,本次會話中的內容都會被回滾 - 你也可以將調試會話設置成同步模式,但是此時必須注意調試時會影響
Redis
所有其他的操作,且調試會話產生的結果都會被保存下來
Redis Lua調試器快速入門
想看視頻的直接點這裏,這是Redis
之父錄製的視頻。
想看文字的繼續。以我們在剛開始提供的Lua
腳本,假設其目錄爲~/Desktop/tmp/test.lua
。此時執行命令(需要先cd
到redis-cli
命令目錄下):
-- async mode
redis-cli --ldb --eval redis_lua_file redis_key , param1 param2
-- sync mode
redis-cli --ldb-sync-mode --eval redis_lua_file redis_key , param1 param2
~ redis-cli --ldb --eval ~/Desktop/tmp/test.lua key , 1 3
Lua debugging session started, please use:
quit -- End the session.
restart -- Restart the script in debug mode again.
help -- Show Lua script debugging commands.
* Stopped at 6, stop reason = step over
-> 6 local key = KEYS[1]
lua debugger>
注意:
redis-cli
裏的逗號前後都是有空格的。我這裏示例是本地有開啓redis-server
,如果沒有開啓也可以連接到遠程redis server
進行調試。另外,key
表示的是要傳入腳本中處理的redis key
,其後的1和3則是參數,中間用空格隔開。
之後所要做的就是在debugger
裏輸入s
命令回車,表示執行下一步,直至程序結束或有異常退出爲止。