一,Redis和Lua結合redis
1:redis.call:在腳本中調用Redis命令,遇到錯誤會直接返回緩存
2:redis.pcall:在腳本中調用Redis命令,遇到錯誤會記錄錯誤並繼續執行安全
3:Lua數據類型和Redis返回值類型對應服務器
(1)數字——整數dom
(2)字符串——字符串模塊化
(3)表類型——多行字符串函數
(4)表類型(只有一個ok字段存儲狀態信息)——狀態回覆ui
(5)表類型(只有一個err字段存儲錯誤信息)——錯誤回覆this
4:eval命令:在Redis中執行腳本編碼
(1)格式是:eval 腳本內容key參數數量[key…] [arg…]
(2)經過key和arg兩類參數來向腳本傳遞數據,在腳本中分別用KEYS和ARGV來獲取
注意:
對於KEYS和ARGV的使用並非強制的,也能夠不從KEYS去獲取鍵,而是在腳本中硬
編碼,好比:redis.call(‘get’,’user:’..ARGV[1]) 0 key1 ,照樣能取
到」user:key1」對應的值。
可是這種寫法,就沒法兼容集羣,也就是說不能在集羣中使用。要兼容集羣,建議
的方式是在客戶端獲取全部的key,而後經過KEYS傳到腳本中。
5:evalsha命令:能夠經過腳本摘要來運行,其餘同eval。執行的時候會根據摘要去找緩存的
腳本,找到了就執行,不然會返回錯誤。
6:script load:將腳本加入緩存,返回值就是SHA1摘要
7:script exists:判斷腳本是否已經緩存
8:script flush:清空腳本緩存
9:script kill:強制終止腳本的執行,若是腳本中修改了某些數據,那麼不會終止腳本的執
行,以保證腳本執行的原子性
二,沙箱
爲了保證Redis服務器的安全,而且要確保腳本的執行結果只和腳本執行時
傳遞的參數有關,Redis禁止腳本中使用操做文件或系統調用相關的函數,腳本
中只能對Redis數據進行操做,這就是沙箱。
Redis會禁用腳本的全局變量,以保證腳本之間是隔離的,互不相干的。
三, Redis對隨機數和隨機結果的處理
1:爲了確保執行結果能夠重現,Redis對隨機數的功能進行了處理,以保證每次執
行腳本生成的隨機數列都相同
2:Redis還對產生隨機結果進行了處理,好比smembers或hkeys等,數據都是無序
的,Redis會對結果按照字典進行順序排序
3:對於會產生隨機結果但沒法排序的命令,好比指揮產生一個元素,Redis會在這
類命令執行後,把該腳本標記爲lua_random_dirty,此後只容許調用讀命令,不
許修改,不然返回錯誤,這類Redis命令有:spop、srandmember、randomkey、
time。
四,MetaTable
用來實現重載操做符功能,基本示例以下:
1:自定義操做的函數,示例:
myAdd={}
function myAdd.__add(f1,f2)
--具體的操做
end
2:爲已有的table設置自定義的操做模板,示例:
setmetatable(tableA,myAdd)
setmetatable(tableB,myAdd)
3:對兩個table作加的操做,示例:
tableA+tableB
這個時候就會調用自定義的myAdd了,等於重載了默認的_add方法,myAdd的__add方法就是MetaMethod
4:Lua內建約定的MetaMethod :
__add(a, b) 、__sub(a, b)、__mul(a, b)、__div(a, b)、__mod(a, b)、__pow(a, b) 、
__unm(a) 取反、__concat(a, b)、__len(a)、__eq(a, b)、__lt(a, b)、__le(a, b)、__index(a, b)
對應表達式a.b、__newindex(a, b, c) 對應表達式a.b = c、__call(a, ...)
五,面向對象
Lua腳本的面向對象相似於JavaScript的面向對象,都是模擬的,好比:
1:直接建立對象:local user={userId='user1',userName='sishuok'}
2:添加新屬性:user.age = 12
3:添加方法
function user:show(a)
redis.log(redis.LOG_NOTICE,'a='..a..',age='..self['age'])
end
裏面的self就至關於this
4:就能夠調用方法了:user:show('abc')
5:作個子類來繼承user:
local child={address='bj'}
setmetatable(child,{__index=user})
__index在這裏起的做用就相似於JS中的Prototype
6:繼承了天然就能夠調用父類的屬性和方法了:child:show('child')
7:固然你還能夠定義本身的方法去覆蓋父類的方法:
function child:show(a)
redis.log(redis.LOG_NOTICE,'child='..a..',age='..self['age']..',address=='..self.address)
end
六,模塊化
注意:這種方式不能在Redis中使用,目前不支持
1:能夠直接使用require(「model_name」)來載入別的lua文件,文件的後綴
是.lua。載入的時候就會直接執行那個文件
2:載入一樣的lua文件時,只有第一次的時候會去執行,後面的相同的都不執行了
3:若是要讓每一次文件都執行,可以使用dofile(「model_name」)函數
4:若是要載入後不執行,等須要的時候執行,可以使用loadfile(「model_name」)
函數,這種是把loadfile的結果賦值給一個變量,好比:
local abc = loadfile(「載入的lua」) 後面須要運行時: abc()