Redis Lua腳本原理


2.6版本之后支持嵌入Lua腳本,客戶端使用Lua腳本,直接在服務器端原子的執行多條命令

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命令:

  • 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加載的腳本都保存在字典中。

字典的作用:實現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!'" 0

腳本管理命令實現

SCRIPT FLUSH 用於清除服務器中lua有關的腳本,釋放lua_scripts字典,關閉現有的lua環境,並重新創建
SCRIPT EXISTS 輸入SHA1校驗和,判斷是否存在
SCRIPT LOAD 與EVAL相同,創建對應的lua函數,存放到字典中
SCRIPT KILL 使用鈎子定期檢查腳本運行時間,如果沒有執行過,可以使用SCRIPT KILL殺掉;如果執行過,只能使用SHUTDOWN nosave停止服務器

腳本的復制

相同的EVALSHA復制操作,從服務器有可能找不到


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM