2.6版本以後支持嵌入Lua腳本,客戶端使用Lua腳本,直接在服務器端原子的執行多條命令redis
Lua腳本執行過程
建立並修改Lua環境數組
- 1 建立基礎Lua環境
- 2 載入函數庫
- 3 建立全局表格Lua
- 4 替換隨機函數
- 5 建立排序輔助函數
- 6 建立redis.pcall函數
- 7 全局環境保護
- 8 修改後的Lua環境保存到服務器狀態的Lua屬性,等待腳本執行
Redis中帶有不肯定性的命令:
SINTER
SUNION
SDIFF
SMEMEBERS
HKEYS
HVALS
KEYS
注意:服務器
- Redis提供了排序函數,使用上述命令後,會返回相同的排序結果
- Redis確保檢查建立變量時,添加local等參數,可是沒有禁止修改已經存在的全局變量,所以使用時應謹慎。
- 因爲Redis使用串行化的方式執行,所以某一特定時間,只有一個腳本能被放進Lua環境裏面運行。
環境協做組件
環境組件:函數
- 一個是用於執行Lua腳本的僞客戶端
- 一個用於保存Lua腳本的字典。
執行Lua腳本的僞客戶端
使用redis.call或者redis.pcall執行Redis命令:lua
- 1 將redis.call或者redis.pcall傳給僞客戶端
- 2 僞客戶端將執行的命令傳給執行器
- 3 執行器執行命令,返回給僞客戶端
- 4 僞客戶端把結果返回給Lua環境
- 5 Lua環境把結果返回給redis.call或者redis.pcall函數
- 6 redis.call或者redis.pcall返回結果給調用者
lua_scripts字典
保存Lua腳本的SHA1【校驗和】checksum,值是對應的腳本。Redis會把EVAL命令執行過的腳本,或者SCRIPT LOAD加載的腳本都保存在字典中。
code
字典的做用:實現SCRIPT EXISTS命令;實現腳本的複製排序
EVAL命令的實現
- 1 根據客戶端給定的腳本,在Lua環境中定義Lua函數
- 2 將客戶端給定的腳本保存到lua_scripts字段,進一步使用
- 3 執行剛剛在lua中定義的函數,執行客戶端給定的lua腳本
經過函數保存傳入的腳本好處:
- 1 執行方便
- 2 保持局部性
- 3 若是定義過一次,只要使用校驗和便可。
準備執行腳本:
- 1 將EVAL命令傳入的鍵名參數和腳本參數保存在KEYS數組和ARGV數組中
- 2 裝載超時鉤子
- 3 執行腳本函數
- 4 移除鉤子
- 5 結果放入緩衝區
- 5 垃圾回收
使用EVALSHA 「xxx校驗和」0 就可執行EVAL "return 'hello world!'" 0ip
腳本管理命令實現
SCRIPT FLUSH 用於清除服務器中lua有關的腳本,釋放lua_scripts字典,關閉現有的lua環境,並從新建立
SCRIPT EXISTS 輸入SHA1校驗和,判斷是否存在
SCRIPT LOAD 與EVAL相同,建立對應的lua函數,存放到字典中
SCRIPT KILL 使用鉤子按期檢查腳本運行時間,若是沒有執行過,能夠使用SCRIPT KILL殺掉;若是執行過,只能使用SHUTDOWN nosave中止服務器
腳本的複製
相同的EVALSHA複製操做,從服務器有可能找不到鉤子