本篇內(nèi)容介紹了“go-zero實踐中的緩存設計之如何使用biz cache”的有關知識,在實際案例的操作過程中,不少人都會遇到這樣的困境,接下來就讓小編帶領大家學習一下如何處理這些情況吧!希望大家仔細閱讀,能夠?qū)W有所成!
成都創(chuàng)新互聯(lián)公司專注于博野企業(yè)網(wǎng)站建設,自適應網(wǎng)站建設,商城網(wǎng)站建設。博野網(wǎng)站建設公司,為博野等地區(qū)提供建站服務。全流程按需網(wǎng)站建設,專業(yè)設計,全程項目跟蹤,成都創(chuàng)新互聯(lián)公司專業(yè)和態(tài)度為您提供的服務
選課系統(tǒng)
內(nèi)容社交系統(tǒng)
秒殺
像這些系統(tǒng),我們可以在業(yè)務層再增加一層緩存來存儲系統(tǒng)中的關鍵信息,如選課系統(tǒng)中學生選課信息,課程剩余名額;內(nèi)容社交系統(tǒng)中某一段時間之間的內(nèi)容信息等。
接下來,我們以內(nèi)容社交系統(tǒng)來進行舉例說明。
在內(nèi)容社交系統(tǒng)中,我們一般是先查詢一批內(nèi)容列表,然后點擊某條內(nèi)容查看詳情,
在沒有添加biz緩存前,內(nèi)容信息的查詢流程圖應該為:
從上圖以及上一篇文章 緩存設計的好,服務基本不會倒 中我們可以知道,內(nèi)容列表的獲取是沒辦法依賴緩存的, 如果我們在業(yè)務層添加一層緩存用來存儲列表中的關鍵信息(甚至完整信息),那么多行記錄的訪問不再是一個問題,這就是biz redis要做的事情。 接下來我們來看一下設計方案,假設內(nèi)容系統(tǒng)中單行記錄包含以下字段
字段名稱 | 字段類型 | 備注 |
---|---|---|
id | string | 內(nèi)容id |
title | string | 標題 |
content | string | 詳細內(nèi)容 |
createTime | time.Time | 創(chuàng)建時間 |
我們的目標是獲取一批內(nèi)容列表,而盡量避免內(nèi)容列表走db造成訪問壓力,首先我們采用redis的sort set數(shù)據(jù)結構來存儲,根需要存儲的字段信息量,有兩種redis存儲方案:
緩存局部信息 對其關鍵字段信息(如:id等)按照一定規(guī)則壓縮,并存儲,score我們用createTime
毫秒值(時間值相等這里不討論),這種存儲方案的好處是節(jié)約redis存儲空間, 那另一方面,缺點就是需要對列表詳細內(nèi)容進行二次回查(但這次回查是會利用到持久層的行記錄緩存的)
緩存完整信息 對發(fā)布的所有內(nèi)容按照一定規(guī)則壓縮后均進行存儲,同樣score我們還是用createTime
毫秒值,這種存儲方案的好處是業(yè)務的增、刪、查、改均走reids,而db層這時候 就可以不用考慮行記錄緩存了,持久層僅提供數(shù)據(jù)備份和恢復使用,從另一方面來看,其缺點也很明顯,需要的存儲空間、配置要求更高,費用也會隨之增大。
示例代碼:
type Content struct { Id string `json:"id"` Title string `json:"title"` Content string `json:"content"` CreateTime time.Time `json:"create_time"` } const bizContentCacheKey = `biz#content#cache` // AddContent 提供內(nèi)容存儲 func AddContent(r redis.Redis, c *Content) error { v := compress(c) _, err := r.Zadd(bizContentCacheKey, c.CreateTime.UnixNano()/1e6, v) return err } // DelContent 提供內(nèi)容刪除 func DelContent(r redis.Redis, c *Content) error { v := compress(c) _, err := r.Zrem(bizContentCacheKey, v) return err } // 內(nèi)容壓縮 func compress(c *Content) string { // todo: do it yourself var ret string return ret } // 內(nèi)容解壓 func uncompress(v string) *Content { // todo: do it yourself var ret Content return &ret } // ListByRangeTime提供根據(jù)時間段進行數(shù)據(jù)查詢 func ListByRangeTime(r redis.Redis, start, end time.Time) ([]*Content, error) { kvs, err := r.ZrangebyscoreWithScores(bizContentCacheKey, start.UnixNano()/1e6, end.UnixNano()/1e6) if err != nil { return nil, err } var list []*Content for _, kv := range kvs { data := uncompress(kv.Key) list = append(list, data) } return list, nil }
在以上例子中,redis是沒有設置過期時間的,我們將增、刪、改、查操作均同步到redis,我們認為內(nèi)容社交系統(tǒng)的列表訪問請求是比較高的情況下才做這樣的方案設計, 除此之外,還有一些數(shù)據(jù)訪問,沒有像內(nèi)容設計系統(tǒng)這么頻繁的訪問, 可能是某一時間段內(nèi)訪問量突如其來的增加,之后可能很長一段時間才會再訪問一次,以此間隔,或者說不會再訪問了,面對這種場景,我們又該如何考慮緩存的設計呢?在go-zero內(nèi)容實踐中,有兩種方案可以解決這種問題:
增加內(nèi)存緩存:通過內(nèi)存緩存來存儲當前可能突發(fā)訪問量比較大的數(shù)據(jù),常用的存儲方案采用map數(shù)據(jù)結構來存儲,map數(shù)據(jù)存儲實現(xiàn)比較簡單,但緩存過期處理則需要增加定時器來處理,另一宗方案是通過go-zero庫中的 Cache ,其是專門用于內(nèi)存緩存管理。
采用biz redis,并設置合理的過期時間
“go-zero實踐中的緩存設計之如何使用biz cache”的內(nèi)容就介紹到這里了,感謝大家的閱讀。如果想了解更多行業(yè)相關的知識可以關注創(chuàng)新互聯(lián)網(wǎng)站,小編將為大家輸出更多高質(zhì)量的實用文章!