三、Redis執行Lua腳本


前言:

  前面我們已經分析了如何實現分布式鎖,以及在實現的過程中分布式鎖存在的各種問題,並且提出了解決辦法,雖然我們上面看似實現了分布式鎖,但是卻存在一個致命問題,原子性問題,無論是獲取鎖還是釋放鎖,都是用多行Redis命令來實現,如果無法保證這個命令執行的原子性,則整個過程中就存在安全問題,在這里我們要引入另一門語言Lua,Lua腳本語言則可以用來解決多行Redis命令原子性問題,下面來看一下Lua腳本語言;

一、Redis中如何執行Lua腳本:

  1.EVAL命令:

    

     執行一個腳本包括參數:

      script:腳本內容或者腳本地址;

      numkeys:腳本中用到的key的數量,接下來的numkeys個數會作為key的參數,剩下的作為arg的參數;

      arg:其他參數,會被存入腳本環境中的ARGV數組中,角標從1開始;

    示例:EVAL "return 'hello world'" 0,其中

      "return 'hello world'":就是腳本的內容,在這里這幾返回一個字符串;

      0:也就是說沒有用到key參數,直接返回

    效果:

      

   2、SCRIPT LOAD命令:

    

    將一個腳本編譯並且緩存起來,生成一個SHA1值並且返回,為了方便使用,參數script就是腳本內容貨地址;

    一上面腳本為案例演示:

      

   3、EVALSHA命令:

    

    與EVAL類似,執行一段腳本,區別是通過腳本的sha1值執行,去腳本緩存中查詢,然后執行,參數:

      sha1:就是腳本對應的sha1值;

    示例:

    

二、Lua腳本的基本語法:

  Lua的詳細語法可以參考網上的一些網站學習,列如:Lua菜鳥教程,學習任何一門語言都是從基本的如:變量、數據類型、循環、邏輯判斷、運算等入手的,Lua的語法與java有很多相似之處,具體的就不一一細說了,在這里只舉例一些最基本的用法:

  1、聲明變量:  

-- test.lua 文件腳本
a = 5               -- 全局變量
local b = 5         -- 局部變量

   2、打印結果; 

> print("Hello World!")
Hello World!
>

  3、條件控制:

if(布爾表達式)
then
   --[ 布爾表達式為 true 時執行該語句塊 --]
else
   --[ 布爾表達式為 false 時執行該語句塊 --]
end

  4、循環語句:

while( true )
do
   print("循環將永遠執行下去")
end

  5、Lua調用Redis指令:

    當我們在Redis中允許Lua腳本時,有一個內置變量redis,並且具備兩個函數:

      redis.call("命令名稱",參數1,參數2):執行redis命令,執行遇到錯誤會直接返回;

      redis.pcall("命令名稱",參數1,參數2):執行redis命令,遇到錯誤時,錯誤會以Lua腳本的方式返回;

    例如:

      redis.call('SET' ,'num' , '123'):執行這段腳本含義的的redis命令就是:set num 123;

      

    不過我們編寫腳本的時候不希望把set后面的key和value寫死,而是可以由調用腳本的人來指定,把key和value做為參數傳入腳本中,在EVAL執行腳本是接受參數,key和arg,並且會用兩個內置變量(數格式)來接受用戶傳來的參數,像這樣:

      KEYS:用來存放key參數;

      ARGV:用來存放key以外的參數;

    我們在腳本中,可以從數組中根據角標取出用戶傳入的參數,如下;

      redis.call('SET', KEYS[1], ARGV[1]):

    然后,我們執行腳本使可以動態key即需要存放的的value值:

      EVAL "return redis.call('SET', KEYS[1], ARGV[1])" 1 num 123:

      


免責聲明!

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



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