Redis使用之Lua腳本

Lua腳本

Lua是一個高效的輕量級腳本語言,用標(biāo)準(zhǔn)C語言編寫并以源代碼形式開放较鼓, 其設(shè)計目的是為了嵌入應(yīng)用程序中椎木,從而為應(yīng)用程序提供靈活的擴(kuò)展和定制功能。

使用腳本的好處

  1. 減少網(wǎng)絡(luò)開銷博烂,在Lua腳本中可以把多個命令放在同一個腳本中運(yùn)行香椎。
  2. 原子操作,Redis會將整個腳本作為一個整體執(zhí)行脖母,中間不會被其他命令插入士鸥。換句話說,編寫腳本的過程中無需擔(dān)心會出現(xiàn)競態(tài)條件谆级。
  3. 復(fù)用性烤礁,客戶端發(fā)送的腳本會永遠(yuǎn)存儲在Redis中,這意味著其他客戶端可以復(fù)用這一腳本來完成同樣的邏輯肥照。

Lua在Linux中的安裝

到官網(wǎng)下載lua的tar.gz的源碼包
tar -zxvf lua.tar.gz
進(jìn)入解壓的目錄:
cd lua
make linux  (linux環(huán)境下編譯)
make install
如果報錯脚仔,說找不到readline/readline.h, 可以通過yum命令安裝
yum -y install readline-devel ncurses-devel
安裝完以后再make linux  / make install
最后,直接輸入 lua命令即可進(jìn)入lua的控制臺

Redis與Lua

在Lua腳本中調(diào)用Redis命令舆绎,可以使用redis.call函數(shù)調(diào)用鲤脏。比如我們調(diào)用string類型的命令。
redis.call(‘set’,’hello’,’world’)
redis.call 函數(shù)的返回值就是redis命令的執(zhí)行結(jié)果吕朵。redis.call函數(shù)會將這5種類型的返回值轉(zhuǎn)化對應(yīng)的Lua的數(shù)據(jù)類型猎醇。

  • 從Lua腳本中獲得返回值
    在很多情況下我們都需要腳本可以有返回值,在腳本中可以使用return 語句將值返回給redis客戶端努溃,通過return語句來執(zhí)行硫嘶,如果沒有執(zhí)行return,默認(rèn)返回為nil梧税。
  • 如何在redis中執(zhí)行l(wèi)ua腳本
    Redis提供了EVAL命令可以使開發(fā)者像調(diào)用其他Redis內(nèi)置命令一樣調(diào)用腳本沦疾。
    [EVAL] [腳本內(nèi)容] [key參數(shù)的數(shù)量] [key …] [arg …]
    可以通過key和arg這兩個參數(shù)向腳本中傳遞數(shù)據(jù),他們的值可以在腳本中分別使用KEYS和ARGV 這兩個類型的全局變量訪問第队。比如我們通過腳本實現(xiàn)一個set命令哮塞,通過在redis客戶端中調(diào)用,那么執(zhí)行的語句是:
    lua腳本的內(nèi)容為: return redis.call(‘set’,KEYS[1],ARGV[1]) //KEYS和ARGV必須大寫
    eval "return redis.call('set',KEYS[1],ARGV[1])" 1 hello world
    EVAL命令是根據(jù) key參數(shù)的數(shù)量-也就是上面例子中的1來將后面所有參數(shù)分別存入腳本中KEYS和ARGV兩個表類型的全局變量凳谦。當(dāng)腳本不需要任何參數(shù)時也不能省略這個參數(shù)忆畅。如果沒有參數(shù)則為0
    eval "return redis.call(‘get’,’hello’)" 0
  • EVALSHA命令
    考慮到我們通過eval執(zhí)行l(wèi)ua腳本,腳本比較長的情況下尸执,每次調(diào)用腳本都需要把整個腳本傳給redis邻眷,比較占用帶寬眠屎。為了解決這個問題,redis提供了EVALSHA命令允許開發(fā)者通過腳本內(nèi)容的SHA1摘要來執(zhí)行腳本肆饶。該命令的用法和EVAL一樣,只不過是將腳本內(nèi)容替換成腳本內(nèi)容的SHA1摘要岖常。
  1. Redis在執(zhí)行EVAL命令時會計算腳本的SHA1摘要并記錄在腳本緩存中驯镊。
  2. 執(zhí)行EVALSHA命令時Redis會根據(jù)提供的摘要從腳本緩存中查找對應(yīng)的腳本內(nèi)容,如果找到了就執(zhí)行腳本竭鞍,否則返回“NOSCRIPT No matching script,Please use EVAL”板惑。

通過案例來演示EVALSHA命令的效果

script load "return redis.call('get','hello')" 將腳本加入緩存并生成sha1命令
evalsha "a5a402e90df3eaeca2ff03d56d99982e05cf6574" 0
調(diào)用eval命令之前,先執(zhí)行evalsha命令偎快,如果提示腳本不存在冯乘,則再調(diào)用eval命令。

Lua腳本實戰(zhàn)

需求:實現(xiàn)一個針對某個手機(jī)號的訪問頻次?

local num=redis.call('incr',KEYS[1])
if tonumber(num)==1 then
   redis.call('expire',KEYS[1],ARGV[1])
   return 1
elseif tonumber(num)>tonumber(ARGV[2]) then
   return 0
else
   return 1
end

執(zhí)行命令:./redis-cli --eval xxx.lua rate.limiting:13700000000 , 10 3
語法為: ./redis-cli –eval [lua腳本] [key…]空格,空格[args…]

腳本的原子性

Redis的腳本執(zhí)行是原子的晒夹,即腳本執(zhí)行期間Redis不會執(zhí)行其他命令裆馒。所有的命令必須等待腳本執(zhí)行完以后才能執(zhí)行。為了防止某個腳本執(zhí)行時間過程導(dǎo)致Redis無法提供服務(wù)丐怯。Redis提供了lua-time-limit參數(shù)限制腳本的最長運(yùn)行時間喷好。默認(rèn)是5秒鐘。
當(dāng)腳本運(yùn)行時間超過這個限制后读跷,Redis將開始接受其他命令但不會執(zhí)行(以確保腳本的原子性)梗搅,而是返回BUSY的錯誤。

實踐操作

打開兩個客戶端窗口
在第一個窗口中執(zhí)行l(wèi)ua腳本的死循環(huán) eval “while true do end” 0
在第二個窗口中運(yùn)行g(shù)et hello
第二個窗口的運(yùn)行結(jié)果是Busy, 可以通過script kill命令終止正在執(zhí)行的腳本效览。如果當(dāng)前執(zhí)行的lua腳本對redis的數(shù)據(jù)進(jìn)行了修改无切,比如(set)操作,那么script kill命令沒辦法終止腳本的運(yùn)行丐枉,因為要保證lua腳本的原子性哆键。如果執(zhí)行一部分終止了,就違背了這一個原則在這種情況下矛洞,只能通過 shutdown nosave命令強(qiáng)行終止洼哎。

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市沼本,隨后出現(xiàn)的幾起案子噩峦,更是在濱河造成了極大的恐慌,老刑警劉巖抽兆,帶你破解...
    沈念sama閱讀 218,525評論 6 507
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件识补,死亡現(xiàn)場離奇詭異,居然都是意外死亡辫红,警方通過查閱死者的電腦和手機(jī)凭涂,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,203評論 3 395
  • 文/潘曉璐 我一進(jìn)店門祝辣,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人切油,你說我怎么就攤上這事蝙斜。” “怎么了澎胡?”我有些...
    開封第一講書人閱讀 164,862評論 0 354
  • 文/不壞的土叔 我叫張陵孕荠,是天一觀的道長。 經(jīng)常有香客問我攻谁,道長稚伍,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 58,728評論 1 294
  • 正文 為了忘掉前任戚宦,我火速辦了婚禮个曙,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘受楼。我一直安慰自己垦搬,他們只是感情好,可當(dāng)我...
    茶點故事閱讀 67,743評論 6 392
  • 文/花漫 我一把揭開白布那槽。 她就那樣靜靜地躺著悼沿,像睡著了一般。 火紅的嫁衣襯著肌膚如雪骚灸。 梳的紋絲不亂的頭發(fā)上糟趾,一...
    開封第一講書人閱讀 51,590評論 1 305
  • 那天,我揣著相機(jī)與錄音甚牲,去河邊找鬼义郑。 笑死,一個胖子當(dāng)著我的面吹牛丈钙,可吹牛的內(nèi)容都是我干的非驮。 我是一名探鬼主播,決...
    沈念sama閱讀 40,330評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼雏赦,長吁一口氣:“原來是場噩夢啊……” “哼劫笙!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起星岗,我...
    開封第一講書人閱讀 39,244評論 0 276
  • 序言:老撾萬榮一對情侶失蹤填大,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后俏橘,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體允华,經(jīng)...
    沈念sama閱讀 45,693評論 1 314
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 37,885評論 3 336
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發(fā)現(xiàn)自己被綠了靴寂。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片磷蜀。...
    茶點故事閱讀 40,001評論 1 348
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖百炬,靈堂內(nèi)的尸體忽然破棺而出褐隆,到底是詐尸還是另有隱情,我是刑警寧澤收壕,帶...
    沈念sama閱讀 35,723評論 5 346
  • 正文 年R本政府宣布妓灌,位于F島的核電站,受9級特大地震影響蜜宪,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜祥山,卻給世界環(huán)境...
    茶點故事閱讀 41,343評論 3 330
  • 文/蒙蒙 一圃验、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧缝呕,春花似錦澳窑、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,919評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至栈暇,卻和暖如春麻裁,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背源祈。 一陣腳步聲響...
    開封第一講書人閱讀 33,042評論 1 270
  • 我被黑心中介騙來泰國打工煎源, 沒想到剛下飛機(jī)就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人香缺。 一個月前我還...
    沈念sama閱讀 48,191評論 3 370
  • 正文 我出身青樓手销,卻偏偏與公主長得像,于是被迫代替她去往敵國和親图张。 傳聞我的和親對象是個殘疾皇子锋拖,可洞房花燭夜當(dāng)晚...
    茶點故事閱讀 44,955評論 2 355

推薦閱讀更多精彩內(nèi)容

  • Lua 5.1 參考手冊 by Roberto Ierusalimschy, Luiz Henrique de F...
    蘇黎九歌閱讀 13,798評論 0 38
  • [TOC] 相關(guān)命令 EVAL SCRIPT_LOAD EVALSHA(執(zhí)行之前要求執(zhí)行過EVAL或者SCRIPT...
    志華_C閱讀 5,691評論 0 4
  • 在我還沒上中學(xué)的時候,我就常常聽父輩的人提起我們隔壁村子里曾經(jīng)發(fā)生過的一起詭異事件祸轮。按他們的口述兽埃,具體時間應(yīng)該是發(fā)...
    杉沐柒閱讀 606評論 0 2
  • 沒什么可抱怨的 我覺得現(xiàn)在的自己必須熱血沸騰起來 沒有時間再讓我矯情 就像又一次高考 我沒理由再放任自己隨波逐流 ...
    祭憶__閱讀 172評論 0 0