婷婷综合国产,91蜜桃婷婷狠狠久久综合9色 ,九九九九九精品,国产综合av

主頁 > 知識庫 > Go語言中通過Lua腳本操作Redis的方法

Go語言中通過Lua腳本操作Redis的方法

熱門標簽:惠州電銷防封電話卡 阿里云ai電話機器人 釘釘有地圖標注功能嗎 建造者2地圖標注 黃岡人工智能電銷機器人哪個好 濱州自動電銷機器人排名 汕頭小型外呼系統 浙江高頻外呼系統多少錢一個月 鄭州亮點科技用的什么外呼系統

前言

為了在我的一個基本庫中降低與Redis的通訊成本,我將一系列操作封裝到LUA腳本中,借助Redis提供的EVAL命令來簡化操作。

EVAL能夠提供的特性:

  • 可以在LUA腳本中封裝若干操作,如果有多條Redis指令,封裝好之后只需向Redis一次性發送所有參數即可獲得結果
  • Redis可以保證Lua腳本運行期間不會有其他命令插入執行,提供像數據庫事務一樣的原子性
  • Redis會根據腳本的SHA值緩存腳本,已經緩存過的腳本不需要再次傳輸Lua代碼,減少了通信成本,此外在自己代碼中改變Lua腳本,執行時Redis必定也會使用最新的代碼。

導入常見的Go庫如 "github.com/go-redis/redis",就可以實現以下代碼。

生成一段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
`)

該變量創建時,Lua代碼不會被執行,也不需要有已存的Redis連接。

Redis提供的Lua腳本支持,默認有KEYS、ARGV兩個數組,KEYS代表腳本運行時傳入的若干鍵值,ARGV代表傳入的若干參數。由于Lua代碼需要保持簡潔,難免難以讀懂,最好為這些參數寫一些注釋

注意:上面一段代碼使用``跨行,`所在的行雖然空白回車,也會被認為是一行,報錯時不要看錯代碼行號。

運行一段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腳本將會在一個函數中運行,所有變量必須使用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類型,要轉換為數字類型應當使用to_number

如果腳本運行了很久會發生什么?

Lua腳本運行期間,為了避免被其他操作污染數據,這期間將不能執行其它命令,一直等到執行完畢才可以繼續執行其它請求。當Lua腳本執行時間超過了lua-time-limit時,其他請求將會收到Busy錯誤,除非這些請求是SCRIPT KILL(殺掉腳本)或者SHUTDOWN NOSAVE(不保存結果直接關閉Redis)

更多內容參考以下地址,我這里主要是根據使用Go的經驗提供一些總結。https://redis.io/commands/eval

一段更“復雜”的腳本,它要求在獲取一個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)

總結

以上就是這篇文章的全部內容了,希望本文的內容對大家的學習或者工作具有一定的參考學習價值,如果有疑問大家可以留言交流,謝謝大家對腳本之家的支持。

您可能感興趣的文章:
  • SpringBoot通過RedisTemplate執行Lua腳本的方法步驟
  • Redis執行Lua腳本的好處與示例代碼
  • redis中如何使用lua腳本讓你的靈活性提高5個逼格詳解
  • Redis分布式鎖的實現方式(redis面試題)
  • SpringBoot使用Redisson實現分布式鎖(秒殺系統)
  • SpringBoot集成Redisson實現分布式鎖的方法示例
  • Java Redis分布式鎖的正確實現方式詳解
  • 基于Redis實現分布式鎖的方法(lua腳本版)

標簽:滄州 泰安 晉中 昭通 東營 瀘州 阿壩 駐馬店

巨人網絡通訊聲明:本文標題《Go語言中通過Lua腳本操作Redis的方法》,本文關鍵詞  語,言中,通過,Lua,腳本,操作,;如發現本文內容存在版權問題,煩請提供相關信息告之我們,我們將及時溝通與處理。本站內容系統采集于網絡,涉及言論、版權與本站無關。
  • 相關文章
  • 下面列出與本文章《Go語言中通過Lua腳本操作Redis的方法》相關的同類信息!
  • 本頁收集關于Go語言中通過Lua腳本操作Redis的方法的相關信息資訊供網民參考!
  • 推薦文章
    主站蜘蛛池模板: 锦州市| 博白县| 山东省| 辽阳县| 曲麻莱县| 新丰县| 闸北区| 阳东县| 白山市| 竹溪县| 义乌市| 大丰市| 巨野县| 罗山县| 厦门市| 吐鲁番市| 灵石县| 敦煌市| 司法| 体育| 璧山县| 都兰县| 蛟河市| 连云港市| 东丽区| 康乐县| 建宁县| 邵阳县| 曲阳县| 亚东县| 瑞安市| 阿拉善右旗| 历史| 航空| 江口县| 霞浦县| 阳谷县| 通州区| 涪陵区| 丰顺县| 康平县|