Redis進(jìn)階應(yīng)用:Redis+Lua腳本實(shí)現(xiàn)復(fù)合操作
一、引言
減少網(wǎng)絡(luò)開銷:本來N次網(wǎng)絡(luò)請求的操作,可以用一個請求完成。原先N次請求的邏輯放在Redis服務(wù)器上完成,減少了網(wǎng)絡(luò)往返時延; 原子操作:Redis會將整個腳本作為一個整體執(zhí)行,中間不會被其他命令插入。這是一個重要特性,一定要拿小本本記好。至于為什么是一個原子操作,我們以后再分析; 復(fù)用:客戶端發(fā)送的腳本會永久存儲在Redis中。這樣其他客戶端就可以復(fù)用這一腳本,而不需要使用代碼完成同樣的邏輯。
所以現(xiàn)在流傳一句話:要想學(xué)好Redis,必會Lua Script。
三、通過Lua腳本實(shí)現(xiàn)compare and set
3.1 Redis的EVAL
- Redis 127.0.0.1:6379> EVAL script numkeys key [key ...] arg [arg ...]
script:參數(shù)是一段 Lua 5.1 腳本程序。腳本不必(也不應(yīng)該)定義為一個Lua函數(shù)。 numkeys:用于指定鍵名參數(shù)的個數(shù)。 key [key ...]:從 EVAL 的第三個參數(shù)開始算起,表示在腳本中所用到的Redis鍵(key)。在Lua中,這些鍵名參數(shù)可以通過全局變量 KEYS 數(shù)組,用1為基址的形式訪問( KEYS[1] ,KEYS[2],依次類推)。 arg [arg ...]:附加參數(shù),在Lua中通過全局變量ARGV數(shù)組訪問,訪問的形式和KEYS變量類似( ARGV[1] 、 ARGV[2] ,諸如此類)。
這里借用一下官網(wǎng)的例子。
eval為Redis關(guān)鍵字; 第一個引號中的內(nèi)容就是Lua腳本; 2為參數(shù)個數(shù); key1和key2是KEYS[1]、KEYS[2]的入?yún)ⅲ?nbsp; first和second是ARGV[1],ARGV[2]的入?yún)ⅰ?/span>
大家可以簡單地將KEYS[1],KEYS[2], ARGV[1],ARGV[2]理解為占位符。
3.2 執(zhí)行腳本文件和緩存腳本
如果只能在命令行中寫腳本執(zhí)行,遇到復(fù)雜的腳本程序豈不是會抓狂?
下面我們來看一下,如何讓Redis執(zhí)行Lua腳本文件,同時也驗(yàn)證一下lua腳本的復(fù)用特性(以后我們再也不需要定期批量刪除某些符合特定規(guī)則的key了)。
- Redis 127.0.0.1:6379> SCRIPT LOAD script
- Redis 127.0.0.1:6379> EVALSHA sha1 numkeys key [key ...] arg [arg ...]
Redis提供了一個SCRIPTLOAD命令,命令后面的script即為Lua腳本。命令將腳本script添加到腳本緩存中,但并不立即執(zhí)行這個腳本。執(zhí)行命令后,Redis會返回一個SHA1串,第二個EVALSHA命令即可執(zhí)行。
需要注意的是,腳本可以在緩存中保留無限長的時間,直到執(zhí)行完SCRIPT FLUSH。我們來看一下效果。
3.3 使用Lua腳本實(shí)現(xiàn)compare and set
- if Redis.call('get', KEYS[1]) == ARGV[1] then
- Redis.call('set', KEYS[1], ARGV[2]);
- return 1
- else
- return 0 end
下面我們來測試一下這個腳本。
減少網(wǎng)絡(luò)開銷:不使用腳本的情況下,我們實(shí)現(xiàn)一個compareAndSet至少需要與Redis交互兩次,而現(xiàn)在只需要執(zhí)行一次操作即可完成; 原子操作:得益于Redis的設(shè)計(jì),Redis會將整個腳本作為一個整體執(zhí)行,中間不會被其他命令插入。因此在編寫腳本的過程中無需擔(dān)心出現(xiàn)競態(tài)條件,無需使用事務(wù),感興趣的可以百度或等待以后后續(xù)文章更新; 復(fù)用:可以將一系列操作封裝成一個Lua腳本,存儲在文件或Redis上,下次使用時直接調(diào)用即可。
讀到這里,希望你已經(jīng)對Redis+Lua有了一定的了解,并能使用腳本完成一些簡單的復(fù)合操作。后續(xù)還會繼續(xù)更新一些基于Lua腳本+java程序?qū)崿F(xiàn)的分布式數(shù)據(jù)結(jié)構(gòu),如延遲隊(duì)列、可重入鎖等,感興趣的小伙伴可以持續(xù)關(guān)注。
【本文是51CTO專欄機(jī)構(gòu)宜信技術(shù)學(xué)院的原創(chuàng)文章,微信公眾號“宜信技術(shù)學(xué)院( id: CE_TECH)”】