這篇文章主要為大家展示了“Go語言中如何通過Lua腳本操作Redis”,內(nèi)容簡而易懂,條理清晰,希望能夠幫助大家解決疑惑,下面讓小編帶領(lǐng)大家一起研究并學(xué)習(xí)一下“Go語言中如何通過Lua腳本操作Redis”這篇文章吧。

前言
為了在我的一個基本庫中降低與Redis的通訊成本,我將一系列操作封裝到LUA腳本中,借助Redis提供的EVAL命令來簡化操作。
EVAL能夠提供的特性:
可以在LUA腳本中封裝若干操作,如果有多條Redis指令,封裝好之后只需向Redis一次性發(fā)送所有參數(shù)即可獲得結(jié)果
Redis可以保證Lua腳本運行期間不會有其他命令插入執(zhí)行,提供像數(shù)據(jù)庫事務(wù)一樣的原子性
Redis會根據(jù)腳本的SHA值緩存腳本,已經(jīng)緩存過的腳本不需要再次傳輸Lua代碼,減少了通信成本,此外在自己代碼中改變Lua腳本,執(zhí)行時Redis必定也會使用最新的代碼。
導(dǎo)入常見的Go庫如 "github.com/go-redis/redis",就可以實現(xiàn)以下代碼。
生成一段Lua腳本
// KEYS: key for record
// ARGV: fieldName, currentUnixTimestamp, recordTTL
// Update expire field of record key to current timestamp, and renew key expiration
var updateRecordExpireScript = redis.NewScript(`
redis.call("EXPIRE", KEYS[1], ARGV[3])
redis.call("HSET", KEYS[1], ARGV[1], ARGV[2])
return 1
`)該變量創(chuàng)建時,Lua代碼不會被執(zhí)行,也不需要有已存的Redis連接。
Redis提供的Lua腳本支持,默認(rèn)有KEYS、ARGV兩個數(shù)組,KEYS代表腳本運行時傳入的若干鍵值,ARGV代表傳入的若干參數(shù)。由于Lua代碼需要保持簡潔,難免難以讀懂,最好為這些參數(shù)寫一些注釋
注意:上面一段代碼使用``跨行,`所在的行雖然空白回車,也會被認(rèn)為是一行,報錯時不要看錯代碼行號。
運行一段Lua腳本
updateRecordExpireScript.Run(c.Client, []string{recordKey(key)},
expireField,
time.Now().UTC().UnixNano(), int64(c.opt.RecordTTL/time.Second)).Err()運行時,Run將會先通過EVALSHA嘗試通過緩存運行腳本。如果沒有緩存,則使用EVAL運行,這時Lua腳本才會被整個傳入Redis。
Lua腳本的限制
Redis不提供引入額外的包,例如os等,只有redis這一個包可用。
Lua腳本將會在一個函數(shù)中運行,所有變量必須使用local聲明
return返回多個值時,Redis將會只給你第一個
腳本中的類型限制
腳本返回nil時,Go中得到的是err = redis.Nil(與Get找不到值相同)
腳本返回false時,Go中得到的是nil,腳本返回true時,Go中得到的是int64類型的1
腳本返回{"ok": ...}時,Go中得到的是redis的status類型(true/false)
腳本返回{"err": ...}時,Go中得到的是err值,也可以通過return redis.error_reply("My Error")達成
腳本返回number類型時,Go中得到的是int64類型
傳入腳本的KEYS/ARGV中的值一律為string類型,要轉(zhuǎn)換為數(shù)字類型應(yīng)當(dāng)使用to_number
如果腳本運行了很久會發(fā)生什么?
Lua腳本運行期間,為了避免被其他操作污染數(shù)據(jù),這期間將不能執(zhí)行其它命令,一直等到執(zhí)行完畢才可以繼續(xù)執(zhí)行其它請求。當(dāng)Lua腳本執(zhí)行時間超過了lua-time-limit時,其他請求將會收到Busy錯誤,除非這些請求是SCRIPT KILL(殺掉腳本)或者SHUTDOWN NOSAVE(不保存結(jié)果直接關(guān)閉Redis)
更多內(nèi)容參考以下地址,我這里主要是根據(jù)使用Go的經(jīng)驗提供一些總結(jié)。https://redis.io/commands/eval
一段更“復(fù)雜”的腳本,它要求在獲取一個key值時,如果該值訪問較多,就延長生存周期。此外還要比較更新時間,如果不需要更新,則直接返回取到的值,否則返回redis.Nil
// KEYS: rec:key, key
// ARGV: currentUnixTimestamp, hotHit, recordTTL, ttl
// When there's a hit,
var fetchRecordScript = redis.NewScript(local value = redis.call("GET", KEYS[2]) if(value == nil) then return nil end local hit = redis.call("HINCRBY", KEYS[1], "hit", 1) redis.call("EXPIRE", KEYS[1], ARGV[3]) local minHotHit = tonumber(ARGV[2]) local keyTTL = tonumber(ARGV[4]) if(hit > minHotHit)then keyTTL = keyTTL * 2 end redis.call("EXPIRE", KEYS[2], keyTTL) local expire = tonumber(redis.call("HGET", KEYS[1], "expire")) local unixTime = tonumber(ARGV[1]) if(expire == nil or expire < unixTime) then return nil else return value end)
// KEYS: key for record
// ARGV: fieldName, currentUnixTimestamp, recordTTL
// Update expire field of record key to current timestamp, and renew key expiration
var updateRecordExpireScript = redis.NewScript(redis.call("EXPIRE", KEYS[1], ARGV[3]) redis.call("HSET", KEYS[1], ARGV[1], ARGV[2]) return 1)以上是“Go語言中如何通過Lua腳本操作Redis”這篇文章的所有內(nèi)容,感謝各位的閱讀!相信大家都有了一定的了解,希望分享的內(nèi)容對大家有所幫助,如果還想學(xué)習(xí)更多知識,歡迎關(guān)注創(chuàng)新互聯(lián)成都網(wǎng)站設(shè)計公司行業(yè)資訊頻道!
另外有需要云服務(wù)器可以了解下創(chuàng)新互聯(lián)scvps.cn,海內(nèi)外云服務(wù)器15元起步,三天無理由+7*72小時售后在線,公司持有idc許可證,提供“云服務(wù)器、裸金屬服務(wù)器、高防服務(wù)器、香港服務(wù)器、美國服務(wù)器、虛擬主機、免備案服務(wù)器”等云主機租用服務(wù)以及企業(yè)上云的綜合解決方案,具有“安全穩(wěn)定、簡單易用、服務(wù)可用性高、性價比高”等特點與優(yōu)勢,專為企業(yè)上云打造定制,能夠滿足用戶豐富、多元化的應(yīng)用場景需求。
標(biāo)題名稱:Go語言中如何通過Lua腳本操作Redis-創(chuàng)新互聯(lián)
標(biāo)題URL:http://chinadenli.net/article32/eccsc.html
成都網(wǎng)站建設(shè)公司_創(chuàng)新互聯(lián),為您提供手機網(wǎng)站建設(shè)、建站公司、網(wǎng)站導(dǎo)航、網(wǎng)站策劃、網(wǎng)站設(shè)計、網(wǎng)站制作
聲明:本網(wǎng)站發(fā)布的內(nèi)容(圖片、視頻和文字)以用戶投稿、用戶轉(zhuǎn)載內(nèi)容為主,如果涉及侵權(quán)請盡快告知,我們將會在第一時間刪除。文章觀點不代表本網(wǎng)站立場,如需處理請聯(lián)系客服。電話:028-86922220;郵箱:631063699@qq.com。內(nèi)容未經(jīng)允許不得轉(zhuǎn)載,或轉(zhuǎn)載時需注明來源: 創(chuàng)新互聯(lián)
猜你還喜歡下面的內(nèi)容