Go+Redis緩存設(shè)計(jì)與優(yōu)化實(shí)現(xiàn)
在本節(jié)中,我們將通過一個實(shí)際的項(xiàng)目案例,演示如何在 Go 中使用 Redis 實(shí)現(xiàn)高效的緩存設(shè)計(jì)與優(yōu)化。
業(yè)務(wù)需求
假設(shè)我們正在開發(fā)一個電商平臺,需要緩存商品信息以提高頁面加載速度。商品信息經(jīng)常被查詢,但修改頻率較低,因此使用 Redis 作為緩存會大大減少數(shù)據(jù)庫的查詢壓力。
1. 緩存設(shè)計(jì)
緩存粒度
:我們將每個商品的信息作為一個緩存項(xiàng)進(jìn)行存儲,緩存的鍵為商品的 ID,值為商品的 JSON 數(shù)據(jù)。緩存失效策略
:設(shè)置緩存的過期時間為 10 分鐘,這樣商品信息會在 10 分鐘后自動失效,防止過期數(shù)據(jù)的出現(xiàn)。緩存預(yù)熱
:在系統(tǒng)啟動時,我們通過預(yù)加載常見商品的數(shù)據(jù)到緩存中,減少首次訪問時的緩存未命中的情況。
2. Go+Redis代碼實(shí)現(xiàn)
package main import ( "context" "encoding/json" "fmt" "log" "time" "github.com/go-redis/redis/v8" ) var ctx = context.Background() // 商品結(jié)構(gòu)體 type Product struct { ID string `json:"id"` Name string `json:"name"` Price float64 `json:"price"` } func getProductFromDB(productID string) (*Product, error) { // 模擬從數(shù)據(jù)庫獲取商品數(shù)據(jù) return &Product{ ID: productID, Name: "Example Product", Price: 99.99, }, nil } func getProductFromCache(rdb *redis.Client, productID string) (*Product, error) { // 從緩存中獲取商品數(shù)據(jù) val, err := rdb.Get(ctx, productID).Result() if err == redis.Nil { // 緩存未命中,查詢數(shù)據(jù)庫 return nil, nil } else if err != nil { return nil, err } var product Product err = json.Unmarshal([]byte(val), &product) if err != nil { return nil, err } return &product, nil } func setProductToCache(rdb *redis.Client, product *Product) error { // 將商品數(shù)據(jù)緩存到 Redis productData, err := json.Marshal(product) if err != nil { return err } return rdb.Set(ctx, product.ID, productData, 10*time.Minute).Err() } func getProduct(rdb *redis.Client, productID string) (*Product, error) { // 嘗試從緩存中獲取商品 product, err := getProductFromCache(rdb, productID) if err != nil { return nil, err } if product == nil { // 緩存未命中,查詢數(shù)據(jù)庫并將結(jié)果緩存 product, err = getProductFromDB(productID) if err != nil { return nil, err } err = setProductToCache(rdb, product) if err != nil { return nil, err } } return product, nil } func main() { rdb := redis.NewClient(&redis.Options{ Addr: "localhost:6379", // Redis 地址 Password: "", // 密碼 DB: 0, // 默認(rèn)數(shù)據(jù)庫 }) // 獲取商品 productID := "12345" product, err := getProduct(rdb, productID) if err != nil { log.Fatalf("獲取商品失敗: %v", err) } fmt.Printf("商品信息: %+v\n", product) }
3. 代碼解析
獲取商品信息
:首先,我們嘗試從 Redis 緩存中獲取商品信息。如果緩存未命中,我們會從數(shù)據(jù)庫中查詢商品數(shù)據(jù),并將查詢結(jié)果存入緩存。緩存設(shè)置過期時間
:商品信息被存入緩存時,我們設(shè)置了 10 分鐘的過期時間,這樣緩存會自動失效。緩存穿透與擊穿防范
:通過合理的緩存失效時間和商品信息的緩存設(shè)計(jì),避免了緩存穿透和緩存擊穿的問題。
4. 性能優(yōu)化
通過上述設(shè)計(jì),我們顯著減少了數(shù)據(jù)庫查詢次數(shù),降低了數(shù)據(jù)庫的負(fù)載,提高了系統(tǒng)的響應(yīng)速度和吞吐量。
到此這篇關(guān)于Go+Redis緩存設(shè)計(jì)與優(yōu)化的文章就介紹到這了,更多相關(guān)Go Redis緩存內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
解讀rand.Seed(time.Now().UnixNano())的作用及說明
這篇文章主要介紹了關(guān)于rand.Seed(time.Now().UnixNano())的作用及說明,具有很好的參考價值,希望對大家有所幫助。2023-03-03golang默認(rèn)Logger日志庫在項(xiàng)目中使用Zap日志庫
這篇文章主要為大家介紹了golang默認(rèn)Logger日志庫在項(xiàng)目中使用Zap日志庫,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步早日升職加薪2022-04-04golang實(shí)現(xiàn)unicode轉(zhuǎn)換為字符串string的方法
這篇文章主要介紹了golang實(shí)現(xiàn)unicode轉(zhuǎn)換為字符串string的方法,實(shí)例分析了Go語言編碼轉(zhuǎn)換的相關(guān)技巧,具有一定參考借鑒價值,需要的朋友可以參考下2016-07-07解決Golang并發(fā)工具Singleflight的問題
前段時間在一個項(xiàng)目里使用到了分布式鎖進(jìn)行共享資源的訪問限制,后來了解到Golang里還能夠使用singleflight對共享資源的訪問做限制,于是利用空余時間了解,將知識沉淀下來,并做分享2022-05-05一文帶你吃透Golang中net/http標(biāo)準(zhǔn)庫服務(wù)端
這篇文章將從服務(wù)端(Server)作為切入點(diǎn)和大家分享一下Go語言net/http標(biāo)準(zhǔn)庫的實(shí)現(xiàn)邏輯,進(jìn)而一步步分析http標(biāo)準(zhǔn)庫內(nèi)部是如何運(yùn)作的,感興趣的可以了解下2024-03-03golang 實(shí)現(xiàn)對Map進(jìn)行鍵值自定義排序
這篇文章主要介紹了golang 實(shí)現(xiàn)對Map進(jìn)行鍵值自定義排序,具有很好的參考價值,希望對大家有所幫助。一起跟隨小編過來看看吧2021-04-04