golang?防緩存擊穿singleflight的實(shí)現(xiàn)
一、什么是緩存擊穿
當(dāng)一個(gè)key是熱點(diǎn)key時(shí),一般會(huì)做緩存來(lái)抗大量并發(fā),但當(dāng)緩存失效的一瞬間,這些大量的并發(fā)請(qǐng)求會(huì)擊穿緩存,直接請(qǐng)求數(shù)據(jù)庫(kù)
為了避免緩存擊穿,一種解決方法可以設(shè)置緩存永不過(guò)期,另一種可以使用golang的包 singleflight golang.org/x/sync/singleflight
二、原理
多個(gè)并發(fā)請(qǐng)求對(duì)一個(gè)失效key進(jìn)行數(shù)據(jù)獲取時(shí),只會(huì)有其中一個(gè)去直接獲取數(shù)據(jù),其它請(qǐng)求會(huì)阻塞等待第一個(gè)請(qǐng)求返回給它們結(jié)果
三、實(shí)現(xiàn)
package singleflight import ( "sync" ) var WaitCount int var DirectCount int type Caller struct { val interface{} err error wg sync.WaitGroup } type Group struct { mu sync.RWMutex m map[string]*Caller } func (g *Group) Do(key string, fn func() (interface{}, error)) (interface{}, error) { g.mu.Lock() if g.m == nil { g.m = make(map[string]*Caller) } c, ok := g.m[key] if ok { //阻塞等待其它已經(jīng)執(zhí)行此操作的返回結(jié)果 g.mu.Unlock() c.wg.Wait() WaitCount++ return c.val, c.err } //直接請(qǐng)求獲取數(shù)據(jù) c = &Caller{} g.m[key] = c c.wg.Add(1) g.mu.Unlock() c.val, c.err = fn() c.wg.Done() g.mu.Lock() delete(g.m, key) g.mu.Unlock() DirectCount++ return c.val, c.err }
測(cè)試:
func TestGroup_Do(t *testing.T) { sg := &Group{} wg := sync.WaitGroup{} for i := 0; i < 10000; i++ { fn := func() (interface{}, error) { return i, nil } wg.Add(1) go func() { defer wg.Done() got, err := sg.Do("test-key", fn) _, _ = got, err //t.Log("got:", i) }() } wg.Wait() fmt.Println("waitCount:", WaitCount) fmt.Println("DirectCount:", DirectCount) }
輸出:
waitCount: 8323
DirectCount: 1401
到此這篇關(guān)于golang 防緩存擊穿singleflight的實(shí)現(xiàn)的文章就介紹到這了,更多相關(guān)golang 防緩存擊穿singleflight 內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
Go語(yǔ)言學(xué)習(xí)之JSON編碼解析與使用
這篇文章主要為大家詳細(xì)介紹了Go語(yǔ)言中JSON編碼的解析與使用已經(jīng)JSON與Map、結(jié)構(gòu)體的互相轉(zhuǎn)化,文中的示例代碼講解詳細(xì),需要的可以參考一下2023-02-02Go?Excelize?API源碼閱讀Close及NewSheet方法示例解析
這篇文章主要為大家介紹了Go?Excelize?API源碼閱讀Close及NewSheet方法示例解析,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪2022-08-08Go語(yǔ)言開發(fā)編程規(guī)范命令風(fēng)格代碼格式
這篇文章主要為大家介紹了Go語(yǔ)言開發(fā)編程規(guī)范命令風(fēng)格代碼格式,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪2022-06-06解決golang 反射interface{}做零值判斷的一個(gè)重大坑
這篇文章主要介紹了解決golang 反射interface{}做零值判斷的一個(gè)重大坑,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過(guò)來(lái)看看吧2021-04-04golang微服務(wù)框架基礎(chǔ)Gin基本路由使用詳解
這篇文章主要為大家介紹了golang微服務(wù)框架Gin基本路由的使用示例詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步2021-11-11go獲取協(xié)程(goroutine)號(hào)的實(shí)例
這篇文章主要介紹了go獲取協(xié)程(goroutine)號(hào)的實(shí)例,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過(guò)來(lái)看看吧2020-12-12victoriaMetrics庫(kù)布隆過(guò)濾器初始化及使用詳解
這篇文章主要為大家介紹了victoriaMetrics庫(kù)布隆過(guò)濾器初始化及使用詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步早日升職加薪2022-04-04golang 將[]byte轉(zhuǎn)成16進(jìn)制的實(shí)現(xiàn)
這篇文章主要介紹了golang 將[]byte轉(zhuǎn)成16進(jìn)制的實(shí)現(xiàn),具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過(guò)來(lái)看看吧2020-12-12