欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

Go語(yǔ)言中通過(guò)Lua腳本操作Redis的方法

 更新時(shí)間:2018年01月28日 10:20:25   作者:吃土的漢子  
這篇文章主要給大家介紹了關(guān)于Go語(yǔ)言中通過(guò)Lua腳本操作Redis的方法,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友可以參考借鑒,下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧。

前言

為了在我的一個(gè)基本庫(kù)中降低與Redis的通訊成本,我將一系列操作封裝到LUA腳本中,借助Redis提供的EVAL命令來(lái)簡(jiǎn)化操作。

EVAL能夠提供的特性:

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

導(dǎo)入常見的Go庫(kù)如 "github.com/go-redis/redis",就可以實(shí)現(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)建時(shí),Lua代碼不會(huì)被執(zhí)行,也不需要有已存的Redis連接。

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

注意:上面一段代碼使用``跨行,`所在的行雖然空白回車,也會(huì)被認(rèn)為是一行,報(bào)錯(cuò)時(shí)不要看錯(cuò)代碼行號(hào)。

運(yùn)行一段Lua腳本

 updateRecordExpireScript.Run(c.Client, []string{recordKey(key)}, 
         expireField,
         time.Now().UTC().UnixNano(), int64(c.opt.RecordTTL/time.Second)).Err()

運(yùn)行時(shí),Run將會(huì)先通過(guò)EVALSHA嘗試通過(guò)緩存運(yùn)行腳本。如果沒有緩存,則使用EVAL運(yùn)行,這時(shí)Lua腳本才會(huì)被整個(gè)傳入Redis。

Lua腳本的限制

  • Redis不提供引入額外的包,例如os等,只有redis這一個(gè)包可用。
  • Lua腳本將會(huì)在一個(gè)函數(shù)中運(yùn)行,所有變量必須使用local聲明
  • return返回多個(gè)值時(shí),Redis將會(huì)只給你第一個(gè)

腳本中的類型限制

  • 腳本返回nil時(shí),Go中得到的是err = redis.Nil(與Get找不到值相同)
  • 腳本返回false時(shí),Go中得到的是nil,腳本返回true時(shí),Go中得到的是int64類型的1
  • 腳本返回{"ok": ...}時(shí),Go中得到的是redis的status類型(true/false)
  • 腳本返回{"err": ...}時(shí),Go中得到的是err值,也可以通過(guò)return redis.error_reply("My Error")達(dá)成
  • 腳本返回number類型時(shí),Go中得到的是int64類型
  • 傳入腳本的KEYS/ARGV中的值一律為string類型,要轉(zhuǎn)換為數(shù)字類型應(yīng)當(dāng)使用to_number

如果腳本運(yùn)行了很久會(huì)發(fā)生什么?

Lua腳本運(yùn)行期間,為了避免被其他操作污染數(shù)據(jù),這期間將不能執(zhí)行其它命令,一直等到執(zhí)行完畢才可以繼續(xù)執(zhí)行其它請(qǐng)求。當(dāng)Lua腳本執(zhí)行時(shí)間超過(guò)了lua-time-limit時(shí),其他請(qǐng)求將會(huì)收到Busy錯(cuò)誤,除非這些請(qǐng)求是SCRIPT KILL(殺掉腳本)或者SHUTDOWN NOSAVE(不保存結(jié)果直接關(guān)閉Redis)

更多內(nèi)容參考以下地址,我這里主要是根據(jù)使用Go的經(jīng)驗(yàn)提供一些總結(jié)。https://redis.io/commands/eval

一段更“復(fù)雜”的腳本,它要求在獲取一個(gè)key值時(shí),如果該值訪問(wèn)較多,就延長(zhǎng)生存周期。此外還要比較更新時(shí)間,如果不需要更新,則直接返回取到的值,否則返回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)

總結(jié)

以上就是這篇文章的全部?jī)?nèi)容了,希望本文的內(nèi)容對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,如果有疑問(wèn)大家可以留言交流,謝謝大家對(duì)腳本之家的支持。

相關(guān)文章

  • Golang并發(fā)操作中常見的讀寫鎖詳析

    Golang并發(fā)操作中常見的讀寫鎖詳析

    Golang中的鎖機(jī)制主要包含互斥鎖和讀寫鎖互斥鎖互斥鎖是傳統(tǒng)并發(fā)程序?qū)蚕碣Y源進(jìn)行控制訪問(wèn)的主要手段,這篇文章主要給大家介紹了關(guān)于Golang并發(fā)操作中常見的讀寫鎖的相關(guān)資料,需要的朋友可以參考下
    2021-08-08
  • 初識(shí)Golang?Mutex互斥鎖的使用

    初識(shí)Golang?Mutex互斥鎖的使用

    在學(xué)習(xí)操作系統(tǒng)的時(shí)候,我們應(yīng)該都學(xué)習(xí)過(guò)臨界區(qū)、互斥鎖這些概念,用于在并發(fā)環(huán)境下保證狀態(tài)的正確性。在?Go語(yǔ)言?里面互斥鎖是?sync.Mutex?,我們本篇文章就來(lái)學(xué)習(xí)下為什么要使用互斥鎖、如何使用互斥鎖,以及使用時(shí)的常見問(wèn)題
    2022-10-10
  • Go 語(yǔ)言中 20 個(gè)占位符的整理

    Go 語(yǔ)言中 20 個(gè)占位符的整理

    這篇文章主要介紹了Go 語(yǔ)言中 20 個(gè)占位符的整理,看完本篇文章講學(xué)會(huì)什么是占位符?哪些函數(shù)支持?如何使用占位符?不同的占位符的作用?配合占位符的幾個(gè)標(biāo)記符號(hào)用法?
    2021-10-10
  • go語(yǔ)言中讀取配置文件的方法總結(jié)

    go語(yǔ)言中讀取配置文件的方法總結(jié)

    這篇文章主要為大家詳細(xì)介紹了go語(yǔ)言中讀取配置文件的幾個(gè)常見方法,文中的示例代碼講解詳細(xì),具有一定的借鑒價(jià)值,需要的小伙伴可以參考下
    2023-08-08
  • golang中日期操作之日期格式化及日期轉(zhuǎn)換

    golang中日期操作之日期格式化及日期轉(zhuǎn)換

    在編程中,程序員會(huì)經(jīng)常使用到日期相關(guān)操作,下面這篇文章主要給大家介紹了關(guān)于golang中日期操作之日期格式化及日期轉(zhuǎn)換的相關(guān)資料,文中通過(guò)實(shí)例代碼介紹的非常詳細(xì),需要的朋友可以參考下
    2022-11-11
  • Golang并發(fā)編程重點(diǎn)講解

    Golang并發(fā)編程重點(diǎn)講解

    這篇文章主要介紹了Golang并發(fā)編程,在許多環(huán)境中,實(shí)現(xiàn)對(duì)共享變量的正確訪問(wèn)所需要的微妙之處使并發(fā)編程變得困難。Go鼓勵(lì)一種不同的方法,在這種方法中,共享值在通道中傳遞,實(shí)際上,從不由單獨(dú)的執(zhí)行線程主動(dòng)共享
    2023-04-04
  • 深入學(xué)習(xí)Golang的流程控制

    深入學(xué)習(xí)Golang的流程控制

    Go 語(yǔ)言是一門現(xiàn)代化的編程語(yǔ)言,以其簡(jiǎn)潔高效、并發(fā)安全等特點(diǎn)被越來(lái)越多的開發(fā)者所使用。本文將深入探討 Go 語(yǔ)言中的流程控制,包括條件語(yǔ)句、循環(huán)語(yǔ)句以及控制語(yǔ)句等方面
    2023-05-05
  • 最新評(píng)論