Gone框架介紹18 - redis 分布式緩存 和 分布式鎖

gone是可以高效開發Web服務的Golang依賴注入框架
github地址:https://github.com/gone-io/gone
文檔地址:https://goner.fun/zh/
請幫忙在github上點個 ??吧,這對我很重要 ;萬分感謝!!

文章目錄

  • 利用redis提供分布式鎖和分布式緩存
    • 第一步:將redis相關Goner埋葬到Cemetery
    • 第二步:在配置文件中增加redis相關配置
    • 第三步,使用redis
      • 注入接口
      • 使用分布是緩存
      • 使用分布時鎖
    • 上面例子完整代碼

利用redis提供分布式鎖和分布式緩存

在本文中,我們將分享在gone中如何使用分布式緩存和分布式鎖,其中分布式鎖中實現了一種較為自由的處理方式———“智能鎖”,對一個處理函數進行上鎖,函數執行中會周期性檢測鎖過期的剩余時間并自動給鎖續期,函數執行完后會自動解鎖。

第一步:將redis相關Goner埋葬到Cemetery

什么是 Goner?
什么是 埋葬?
什么是 Cemetery?
參考 Gone的核心概念

在Priest函數中增加_ = goner.RedisPriest(cemetery),如下:

func priest(cemetery gone.Cemetery) error {//使用 goner.RedisPriest 函數,將 redis 相關的Goner 埋葬到 Cemetery 中_ = goner.RedisPriest(cemetery)cemetery.Bury(&redisUser{})return nil
}

第二步:在配置文件中增加redis相關配置

創建配置文件 config/default.properties,內容如下:

# redis服務地址,格式為 `host:port`
redis.server=localhost:6379# redis服務密碼,不配置默認為空
redis.password=

其中,redis服務地址需要改你能訪問到的redis服務地址。

更多配置:

  • redis.max-idle:最大空閑鏈接數,不配置默認為2
  • redis.max-active:最大活躍鏈接數,不配置默認為10
  • redis.db:使用的db,不配置默認為0
  • redis.cache.prefix:key前綴,如果設置了,對redis的增刪改查都會拼接該前綴,拼接方式${prefix}#${key};默認為空

關于配置文件,更多參考:通過內置Goners支持配置文件

第三步,使用redis

注入接口

在需要使用的結構體中注入 接口redis.redis.Cacheredis.Locker,他們的GonerId分別為:gone-redis-cachegone-redis-locker

type redisUser struct {gone.Flagcache  redis.Cache  `gone:"gone-redis-cache"`locker redis.Locker `gone:"gone-redis-locker"`
}

使用分布是緩存

請看下面代碼中的注釋:

func (r *redisUser) UseCache() {key := "gone-address"value := "https://github.com/gone-io/gone"//設置緩存err := r.cache.Put(key,            //第一個參數為 緩存的key,類型為 `string`value,          // 第二參數為 需要緩存的值,類型為any,可以是任意類型;傳入的值會被編碼為 `[]byte` 發往redis10*time.Second, // 第三個參數為 過期時間,類型為 `time.Duration`;省略,表示不設置過期時間)if err != nil {fmt.Printf("err:%v", err)return}//獲取緩存var getValue stringerr = r.cache.Get(key,       //第一個參數為 緩存的key,類型為 `string`&getValue, //第二參數為指針,接收獲取緩存的值,類型為any,可以是任意類型;從redis獲取的值會被解碼為傳入的指針類型)if err != nil {fmt.Printf("err:%v", err)return}fmt.Printf("getValue:%v", getValue)
}

接口上的其他方法:

  • Remove(key string) (err error):用于刪除redis某個key,支持通配符
  • Keys(key string) ([]string, error):使用前綴或者通配符查詢存在哪些key,??該方法慎用
  • Prefix() string:獲取當前緩存配置的key前綴

使用分布時鎖

  1. 鎖定一段時間
func (r *redisUser) UseLock() {lockKey := "gone-lock-key"//嘗試獲取鎖 并 鎖定一段時間//返回的第一個參數為一個解鎖的函數unlock, err := r.locker.TryLock(lockKey,        //第一個參數為 鎖的key,類型為 `string`10*time.Second, //第二參數為 鎖的過期時間,類型為 `time.Duration`)if err != nil {fmt.Printf("err:%v", err)return}//操作完后,需要解鎖defer unlock()//獲取鎖成功后,可以進行業務操作//todo
}

這種方式,使用鎖需要保證在鎖定的時間內能夠執行完所有操作,否則由于鎖過期可能會導致問題。

  1. 鎖定一個操作,操作沒結束會自動給鎖續期,操作結束自動解鎖
func (r *redisUser) LockFunc() {lockKey := "gone-lock-key"err := r.locker.LockAndDo(lockKey, //第一個參數為 鎖的key,類型為 `string`func() { //第二個參數為 需要執行的函數,類型為 `func()`,代表一個操作//獲取鎖成功后,可以進行業務操作//todoprintln("do some options")},100*time.Second, //第三個參數為 鎖的過期時間,類型為 `time.Duration`;第一次加鎖和后續鎖續期都將使用該值5*time.Second,   //第四個參數為 鎖續期的間隔時間,類型為 `time.Duration`;周期性檢查所是否將過期,如果在下個周期內會過期則對鎖續期)if err != nil {fmt.Printf("err:%v", err)}
}

這種方式比較智能,姑且將其稱為“智能鎖”吧!
推薦使用這種方式,可以無腦使用,降低使用的心智負擔。

上面例子完整代碼

例子的源代碼可以在這里找到

package mainimport ("fmt""github.com/gone-io/gone""github.com/gone-io/gone/goner""github.com/gone-io/gone/goner/redis""time"
)func priest(cemetery gone.Cemetery) error {//使用 goner.RedisPriest 函數,將 redis 相關的Goner 埋葬到 Cemetery 中_ = goner.RedisPriest(cemetery)cemetery.Bury(&redisUser{})return nil
}type redisUser struct {gone.Flagcache  redis.Cache  `gone:"gone-redis-cache"`locker redis.Locker `gone:"gone-redis-locker"`
}func (r *redisUser) UseCache() {key := "gone-address"value := "https://github.com/gone-io/gone"//設置緩存err := r.cache.Put(key,            //第一個參數為 緩存的key,類型為 `string`value,          // 第二參數為 需要緩存的值,類型為any,可以是任意類型;傳入的值會被編碼為 `[]byte` 發往redis10*time.Second, // 第三個參數為 過期時間,類型為 `time.Duration`;省略,表示不設置過期時間)if err != nil {fmt.Printf("err:%v", err)return}//獲取緩存var getValue stringerr = r.cache.Get(key,       //第一個參數為 緩存的key,類型為 `string`&getValue, //第二參數為指針,接收獲取緩存的值,類型為any,可以是任意類型;從redis獲取的值會被解碼為傳入的指針類型)if err != nil {fmt.Printf("err:%v", err)return}fmt.Printf("getValue:%v", getValue)
}func (r *redisUser) LockTime() {lockKey := "gone-lock-key"//嘗試獲取鎖 并 鎖定一段時間//返回的第一個參數為一個解鎖的函數unlock, err := r.locker.TryLock(lockKey,        //第一個參數為 鎖的key,類型為 `string`10*time.Second, //第二參數為 鎖的過期時間,類型為 `time.Duration`)if err != nil {fmt.Printf("err:%v", err)return}//操作完后,需要解鎖defer unlock()//獲取鎖成功后,可以進行業務操作//todo
}func (r *redisUser) LockFunc() {lockKey := "gone-lock-key"err := r.locker.LockAndDo(lockKey, //第一個參數為 鎖的key,類型為 `string`func() { //第二個參數為 需要執行的函數,類型為 `func()`,代表一個操作//獲取鎖成功后,可以進行業務操作//todoprintln("do some options")},100*time.Second, //第三個參數為 鎖的過期時間,類型為 `time.Duration`;第一次加鎖和后續鎖續期都將使用該值5*time.Second,   //第四個參數為 鎖續期的間隔時間,類型為 `time.Duration`;周期性檢查所是否將過期,如果在下個周期內會過期則對鎖續期)if err != nil {fmt.Printf("err:%v", err)}
}func main() {gone.Prepare(priest).AfterStart(func(in struct {r *redisUser `gone:"*"`}) {in.r.UseCache()in.r.LockTime()}).Run()
}

上一篇:Gone框架介紹17 - 創建一個可運行在生產環境的Web項目
下一篇:Gone框架介紹19 -如何進行單元測試?

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/diannao/13196.shtml
繁體地址,請注明出處:http://hk.pswp.cn/diannao/13196.shtml
英文地址,請注明出處:http://en.pswp.cn/diannao/13196.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

Python | Leetcode Python題解之第92題反轉鏈表II

題目: 題解: class Solution:def reverseBetween(self, head: ListNode, left: int, right: int) -> ListNode:# 設置 dummyNode 是這一類問題的一般做法dummy_node ListNode(-1)dummy_node.next headpre dummy_nodefor _ in range(left - 1):pre…

云計算第十八課

目錄操作 移動 改名 批量改名,寫腳本 mv [選項] … 源文件或目錄… 目標文件或目錄 單個文件 移動 或者改名 -f:強制覆蓋,如果目標文件已經存在,則不詢問,直接強制覆蓋; -i:交互移動&#x…

零基礎學Java第十四天之抽象類

抽象類和抽象類的深入 抽象類 1、理解 抽象類(Abstract Class)是面向對象編程中的一個重要概念,尤其在像Java、C#和C等編程語言中。抽象類是一種特殊的類,它不能被實例化(即不能創建抽象類的對象)&#x…

鼠標懸浮(hover)時顯示提示框的效果

在Vue中,你可以使用多種方法來實現鼠標懸浮(hover)時顯示提示框的效果。以下是一個簡單的示例,它使用了Vue的指令(directive)和條件渲染(conditional rendering)來實現這個功能。 首…

關于FIFO Generator IP和XPM_FIFO在涉及位寬轉換上的區別

在Xilinx FPGA中,要實現FIFO的功能時,大部分時候會使用兩種方法: FIFO Generator IP核XPM_FIFO原語 FIFO Generator IP核的優點是有圖形化界面,配置參數非常直觀;缺點是參數一旦固定,想要更改的化就只能重…

一次tomcat閃退處理

雙擊tomcat目錄下bin目錄中startup.bat 在我的電腦上是一閃而過,不能正常地啟動tomcat軟件 以記事本打開startup.bat文件,在文件的結尾處加上pause 然后再雙擊該bat執行,此時窗口就不會關閉,并會將錯誤信息打印在提示框中 可能是…

英偉達發布 VILA 視覺語言模型,實現多圖像推理、增強型上下文學習,性能超越 LLaVA-1.5

前言 近年來,大型語言模型 (LLM) 的發展取得了顯著的成果,并逐漸應用于多模態領域,例如視覺語言模型 (VLM)。VLM 旨在將 LLM 的強大能力擴展到視覺領域,使其能夠理解和處理圖像和文本信息,并完成諸如視覺問答、圖像描…

一看就會的AOP事務

文章目錄 AOPAOP簡介AOP簡介和作用AOP的應用場景為什么要學習AOP AOP入門案例思路分析代碼實現AOP中的核心概念 AOP工作流程AOP工作流程AOP核心概念在測試類中驗證代理對象 AOP切入點表達式語法格式通配符書寫技巧 AOP通知類型AOP通知分類AOP通知詳解 AOP案例案例-測量業務層接…

Linux bc命令(bc指令)(基本計算器)(任意精度計算語言:支持浮點數運算、變量賦值和自定義函數等)

文章目錄 bc命令文檔英文中文 Linux bc 命令詳解bc 命令的基本用法啟動 bc 環境進行基本計算退出 bc bc 中的數學功能執行高級數學計算平方根和指數函數對數函數 處理精度問題 變量和數組變量賦值和使用數組的使用 創建和使用自定義函數 bc 命令的高級用法在腳本中使用 bc基本腳…

Google I/O 大會 | 精彩看點一覽

作者 / 開發者關系和開源總監 Timothy Jordan 2024 年 Google I/O 大會于北京時間 5 月 15 日 1:00am 在加利福尼亞的山景城以 Google 主題演講直播拉開序幕。隨后,在北京時間 4:30am 舉行開發者主題演講。大家可前往回看 "Google 主題演講" 以及 "開…

AIGC時代已至,你準備好抓住機遇了嗎?

一、行業前景 AIGC,即人工智能生成內容,是近年來人工智能領域中發展迅猛的一個分支。隨著大數據、云計算、機器學習等技術的不斷進步,AIGC已經取得了顯著的成果,并且在廣告、游戲、自媒體、教育、電商等多個領域實現了廣泛應用。…

AI寫算法:支持向量機(SVM)

在Python中,我們可以使用scikit-learn庫來實現支持向量機(SVM)。以下是一個簡單的示例,演示如何使用scikit-learn的SVC類來訓練一個SVM分類器,并使用它對一些數據進行預測。 python復制代碼 # 導入必要的庫 from skle…

圖像中的attention及QKV機制解釋

簡單記錄/推薦兩篇博客,后續細化寫一下: 圖像中的各類 attention https://blog.csdn.net/weixin_44505185/article/details/127013204 Cross-attention的直觀理解 首先理解,cross-attention 是兩個不同向量間的相關計算,一般Q…

DolphinScheduler(海豚調度)- docker部署實戰

1.官方文檔 https://dolphinscheduler.apache.org/zh-cn/docs/3.2.1/guide/start/docker 2.docker環境安裝 版本情況(這個地方踩了不少坑):docker-26.1.2,docker-compose-v2.11.0。 具體可使用我上傳的安裝包,一鍵安…

leetcode題目55

跳躍游戲 中等 給你一個非負整數數組 nums ,你最初位于數組的 第一個下標 。數組中的每個元素代表你在該位置可以跳躍的最大長度。 判斷你是否能夠到達最后一個下標,如果可以,返回 true ;否則,返回 false 。 示例 1…

MT3037 新月軒就餐

思路: 此題每道菜的價錢相同,想最小化付的錢即求最小區間長度可以滿足“品嘗到所有名廚手藝”。 使用雙端隊列存儲元素,隊尾不斷向后遍歷:頭->尾 如果隊頭隊尾,則隊頭往右移一格,直到區間不同元素數m…

Docker部署MaxKB詳細步驟(window系統)

上面章節已經實現了ollama李現部署llama3,并實現了一些簡單的問答,但是問答的界面是在命令提示符中,交互很不友好,也不方便局域網其他用戶訪問,所以這節用docker部署MaxKB實現網頁訪問llama3,首先電腦上需要…

分布式系統的一致性與共識算法(四)

Etcd與Raft算法 Raft保證讀請求Linearizability的方法: 1.Leader把每次讀請求作為一條日志記錄,以日志復制的形式提交,并應用到狀態機后,讀取狀態機中的數據返回(一次RTT、一次磁盤寫)2.使用Leader Lease,保證整個集群只有一個L…

使用Flask-RESTful構建RESTful API

文章目錄 安裝Flask-RESTful導入模塊和類創建一個資源類運行應用測試API總結 Flask是一個輕量級的Python web開發框架,而Flask-RESTful是一個基于Flask的擴展,專門用于構建RESTful API。它提供了一些幫助類和方法,使構建API變得更加簡單和高效…

詳細分析Vue3中的reactive(附Demo)

目錄 1. 基本知識2. 用法3. Demo 1. 基本知識 reactive 是一個函數,用于將一個普通的 JavaScript 對象轉換為響應式對象 當對象的屬性發生變化時,Vue 會自動追蹤這些變化,并觸發相應的更新 Vue2沒有,而Vue3中有,為啥…