Redis Lua腳本原理

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複製操做,從服務器有可能找不到鉤子

相關文章
相關標籤/搜索