溫馨提示×

溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊×
其他方式登錄
點(diǎn)擊 登錄注冊 即表示同意《億速云用戶服務(wù)條款》

go-zero實(shí)踐中的緩存設(shè)計(jì)之如何使用biz cache

發(fā)布時間:2021-10-15 16:20:57 來源:億速云 閱讀:270 作者:iii 欄目:編程語言

本篇內(nèi)容介紹了“go-zero實(shí)踐中的緩存設(shè)計(jì)之如何使用biz cache”的有關(guān)知識,在實(shí)際案例的操作過程中,不少人都會遇到這樣的困境,接下來就讓小編帶領(lǐng)大家學(xué)習(xí)一下如何處理這些情況吧!希望大家仔細(xì)閱讀,能夠?qū)W有所成!

適用場景舉例

  • 選課系統(tǒng)

  • 內(nèi)容社交系統(tǒng)

  • 秒殺

像這些系統(tǒng),我們可以在業(yè)務(wù)層再增加一層緩存來存儲系統(tǒng)中的關(guān)鍵信息,如選課系統(tǒng)中學(xué)生選課信息,課程剩余名額;內(nèi)容社交系統(tǒng)中某一段時間之間的內(nèi)容信息等。

接下來,我們以內(nèi)容社交系統(tǒng)來進(jìn)行舉例說明。

在內(nèi)容社交系統(tǒng)中,我們一般是先查詢一批內(nèi)容列表,然后點(diǎn)擊某條內(nèi)容查看詳情,

在沒有添加biz緩存前,內(nèi)容信息的查詢流程圖應(yīng)該為:

go-zero實(shí)踐中的緩存設(shè)計(jì)之如何使用biz cache

從上圖以及上一篇文章 緩存設(shè)計(jì)的好,服務(wù)基本不會倒 中我們可以知道,內(nèi)容列表的獲取是沒辦法依賴緩存的, 如果我們在業(yè)務(wù)層添加一層緩存用來存儲列表中的關(guān)鍵信息(甚至完整信息),那么多行記錄的訪問不再是一個問題,這就是biz redis要做的事情。 接下來我們來看一下設(shè)計(jì)方案,假設(shè)內(nèi)容系統(tǒng)中單行記錄包含以下字段

字段名稱字段類型備注
idstring內(nèi)容id
titlestring標(biāo)題
contentstring詳細(xì)內(nèi)容
createTimetime.Time創(chuàng)建時間

我們的目標(biāo)是獲取一批內(nèi)容列表,而盡量避免內(nèi)容列表走db造成訪問壓力,首先我們采用redis的sort set數(shù)據(jù)結(jié)構(gòu)來存儲,根需要存儲的字段信息量,有兩種redis存儲方案:

  • 緩存局部信息 go-zero實(shí)踐中的緩存設(shè)計(jì)之如何使用biz cache 對其關(guān)鍵字段信息(如:id等)按照一定規(guī)則壓縮,并存儲,score我們用createTime毫秒值(時間值相等這里不討論),這種存儲方案的好處是節(jié)約redis存儲空間, 那另一方面,缺點(diǎn)就是需要對列表詳細(xì)內(nèi)容進(jìn)行二次回查(但這次回查是會利用到持久層的行記錄緩存的)

  • 緩存完整信息 go-zero實(shí)踐中的緩存設(shè)計(jì)之如何使用biz cache 對發(fā)布的所有內(nèi)容按照一定規(guī)則壓縮后均進(jìn)行存儲,同樣score我們還是用createTime毫秒值,這種存儲方案的好處是業(yè)務(wù)的增、刪、查、改均走reids,而db層這時候 就可以不用考慮行記錄緩存了,持久層僅提供數(shù)據(jù)備份和恢復(fù)使用,從另一方面來看,其缺點(diǎn)也很明顯,需要的存儲空間、配置要求更高,費(fèi)用也會隨之增大。

示例代碼:

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ù)時間段進(jìn)行數(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是沒有設(shè)置過期時間的,我們將增、刪、改、查操作均同步到redis,我們認(rèn)為內(nèi)容社交系統(tǒng)的列表訪問請求是比較高的情況下才做這樣的方案設(shè)計(jì), 除此之外,還有一些數(shù)據(jù)訪問,沒有像內(nèi)容設(shè)計(jì)系統(tǒng)這么頻繁的訪問, 可能是某一時間段內(nèi)訪問量突如其來的增加,之后可能很長一段時間才會再訪問一次,以此間隔,或者說不會再訪問了,面對這種場景,我們又該如何考慮緩存的設(shè)計(jì)呢?在go-zero內(nèi)容實(shí)踐中,有兩種方案可以解決這種問題:

  • 增加內(nèi)存緩存:通過內(nèi)存緩存來存儲當(dāng)前可能突發(fā)訪問量比較大的數(shù)據(jù),常用的存儲方案采用map數(shù)據(jù)結(jié)構(gòu)來存儲,map數(shù)據(jù)存儲實(shí)現(xiàn)比較簡單,但緩存過期處理則需要增加定時器來處理,另一宗方案是通過go-zero庫中的 Cache ,其是專門用于內(nèi)存緩存管理。

  • 采用biz redis,并設(shè)置合理的過期時間

“go-zero實(shí)踐中的緩存設(shè)計(jì)之如何使用biz cache”的內(nèi)容就介紹到這里了,感謝大家的閱讀。如果想了解更多行業(yè)相關(guān)的知識可以關(guān)注億速云網(wǎng)站,小編將為大家輸出更多高質(zhì)量的實(shí)用文章!

向AI問一下細(xì)節(jié)

免責(zé)聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉(zhuǎn)載和分享為主,文章觀點(diǎn)不代表本網(wǎng)站立場,如果涉及侵權(quán)請聯(lián)系站長郵箱:is@yisu.com進(jìn)行舉報(bào),并提供相關(guān)證據(jù),一經(jīng)查實(shí),將立刻刪除涉嫌侵權(quán)內(nèi)容。

AI