最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

golang中cache組件的使用及groupcache源碼解析

 更新時(shí)間:2021年06月09日 11:41:27   作者:隨風(fēng)奔跑尿飛揚(yáng)  
本篇主要解析groupcache源碼中的關(guān)鍵部分, lru的定義以及如何做到同一個(gè)key只加載一次。緩存填充以及加載抑制的實(shí)現(xiàn)方法,本文重點(diǎn)給大家介紹golang中cache組件的使用及groupcache源碼解析,感興趣的朋友一起看看吧

groupcache 簡(jiǎn)介

在軟件系統(tǒng)中使用緩存,可以降低系統(tǒng)響應(yīng)時(shí)間,提高用戶體驗(yàn),降低某些系統(tǒng)模塊的壓力.
groupcache是一款開源的緩存組件.與memcache與redis不同的時(shí),groupcache不需要單獨(dú)的部署,可以作為你程序的一個(gè)庫(kù)來使用. 這樣方便我們開發(fā)的程序部署.

本篇主要解析groupcache源碼中的關(guān)鍵部分, lru的定義以及如何做到同一個(gè)key只加載一次。

緩存填充以及加載抑制的實(shí)現(xiàn)

上篇有提到load函數(shù)的實(shí)現(xiàn), 緩存填充的邏輯也體現(xiàn)在這里。
groupcache盡量避免從源中獲取數(shù)據(jù),當(dāng)本地?cái)?shù)據(jù)缺失時(shí)會(huì)先從peer中獲取,peer中命中則直接填充到本地,未命中才會(huì)從源中加載,這正是緩存填充的實(shí)現(xiàn)邏輯。
而加載抑制,避免重復(fù)加載的功能是依靠 singleflight包實(shí)現(xiàn)的。
這個(gè)包中主要有兩個(gè)結(jié)構(gòu)體:

call用來存放獲取結(jié)果(val)和錯(cuò)誤(err), 每個(gè)key對(duì)應(yīng)一個(gè)call實(shí)例。wg用來控制請(qǐng)求的等待。

type call struct {
	wg  sync.WaitGroup
	val interface{}
	err error
}

Group用來存放所有的call,記錄所有的請(qǐng)求。

type Group struct {
	mu sync.Mutex       // protects m
	m  map[string]*call // lazily initialized
}

Group.Do是功能的實(shí)現(xiàn)。
當(dāng)接到一個(gè)請(qǐng)求時(shí), 會(huì)首先加鎖, 并初始化用來記錄請(qǐng)求的map。map的鍵為請(qǐng)求的key, 值為call

g.mu.Lock()
if g.m == nil {
	g.m = make(map[string]*call)
}

如果當(dāng)前的key已經(jīng)在請(qǐng)求加載的過程中,那么解除上一步定義的沖突鎖,并等待已經(jīng)存在的加載請(qǐng)求結(jié)束后返回。

if c, ok := g.m[key]; ok {
	g.mu.Unlock()
	c.wg.Wait()
	return c.val, c.err
}

如果當(dāng)前的key沒有已經(jīng)存在的加載過程,那么創(chuàng)建一個(gè)call實(shí)例, 加入到map記錄中,并向call.wg中加入一個(gè)記錄,以阻塞其他請(qǐng)求,解除上一步定義的沖突鎖。

c := new(call)
c.wg.Add(1)
g.m[key] = c
g.mu.Unlock()

調(diào)用傳入的函數(shù)(作者并沒有將這個(gè)功能局限于數(shù)據(jù)獲取,通過傳入的func可以實(shí)現(xiàn)不同功能的控制),將結(jié)果賦值給call,獲取完成后wg.done結(jié)束阻塞。

c.val, c.err = fn()
c.wg.Done()

然后刪除map記錄

g.mu.Lock()
delete(g.m, key)
g.mu.Unlock()

這個(gè)功能的實(shí)現(xiàn)主要是依靠sync.WaitGroup的阻塞實(shí)現(xiàn), 這里也是對(duì)初學(xué)者最難理解的地方。
可以想象一個(gè)場(chǎng)景:
大學(xué)寢室中,你和你的室友都要到食堂買午飯,你對(duì)室友說:“你自己去就行,給我?guī)б环荨?。然后你就在宿舍中等待舍友回來?br /> 在這個(gè)場(chǎng)景中,你和室友就是請(qǐng)求,你在等待就是阻塞

cache(lru)

上篇提到的主緩存和熱緩存均是依靠cache實(shí)現(xiàn)。
cache的實(shí)現(xiàn)依靠雙向鏈表。
MaxEntries 最大的存儲(chǔ)量
OnEvicted當(dāng)發(fā)生驅(qū)逐時(shí)(即到達(dá)MaxEntries)執(zhí)行的操作
ll雙向鏈表本體
cache key對(duì)應(yīng)鏈表中的元素

type Cache struct {
	// MaxEntries is the maximum number of cache entries before
	// an item is evicted. Zero means no limit.
	MaxEntries int

	// OnEvicted optionally specifies a callback function to be
	// executed when an entry is purged from the cache.
	OnEvicted func(key Key, value interface{})

	ll    *list.List
	cache map[interface{}]*list.Element
}

添加時(shí)會(huì)先進(jìn)行初始化map,如果key已存在,那么會(huì)將keyindex提到首位(這里的鏈表不存在index,僅為方便理解),并更新其value。
如果不存在則直接插入到首位。
如果插入后的長(zhǎng)度超過限制, 會(huì)執(zhí)行清理操作

func (c *Cache) Add(key Key, value interface{}) {
	if c.cache == nil {
		c.cache = make(map[interface{}]*list.Element)
		c.ll = list.New()
	}
	if ee, ok := c.cache[key]; ok {
		c.ll.MoveToFront(ee)
		ee.Value.(*entry).value = value
		return
	}
	ele := c.ll.PushFront(&entry{key, value})
	c.cache[key] = ele
	if c.MaxEntries != 0 && c.ll.Len() > c.MaxEntries {
		c.RemoveOldest()
	}
}

清理時(shí)會(huì)刪除尾部元素, 這里就解釋了為什么每次操作時(shí)會(huì)把元素提到首位。

func (c *Cache) RemoveOldest() {
	if c.cache == nil {
		return
	}
	ele := c.ll.Back()
	if ele != nil {
		c.removeElement(ele)
	}
}

以上就是golang中cache組件的使用之groupcache的詳細(xì)內(nèi)容,更多關(guān)于go groupcache用法的資料請(qǐng)關(guān)注腳本之家其它相關(guān)文章!

相關(guān)文章

  • Go語言二維數(shù)組的傳參方式

    Go語言二維數(shù)組的傳參方式

    這篇文章主要介紹了Go語言二維數(shù)組的傳參方式,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過來看看吧
    2021-04-04
  • go單體日志采集zincsearch方案實(shí)現(xiàn)

    go單體日志采集zincsearch方案實(shí)現(xiàn)

    這篇文章主要為大家介紹了go單體日志采集zincsearch方案實(shí)現(xiàn)示例詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪
    2022-07-07
  • golang多維度排序及題解最長(zhǎng)連續(xù)序列

    golang多維度排序及題解最長(zhǎng)連續(xù)序列

    這篇文章主要為大家介紹了golang多維度排序及題解最長(zhǎng)連續(xù)序列示例詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪
    2023-10-10
  • 詳解go基于viper實(shí)現(xiàn)配置文件熱更新及其源碼分析

    詳解go基于viper實(shí)現(xiàn)配置文件熱更新及其源碼分析

    這篇文章主要介紹了詳解go基于viper實(shí)現(xiàn)配置文件熱更新及其源碼分析,文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2020-06-06
  • Go語言使用漏桶算法和令牌桶算法來實(shí)現(xiàn)API限流

    Go語言使用漏桶算法和令牌桶算法來實(shí)現(xiàn)API限流

    為防止服務(wù)器被過多的請(qǐng)求壓垮,限流是一個(gè)至關(guān)重要的技術(shù)手段,下面我們就來看看如何使用漏桶算法和令牌桶算法來實(shí)現(xiàn) API 的限流吧
    2024-11-11
  • go時(shí)間/時(shí)間戳操作大全(小結(jié))

    go時(shí)間/時(shí)間戳操作大全(小結(jié))

    這篇文章主要介紹了go時(shí)間/時(shí)間戳操作大全,文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2019-07-07
  • Go語言如何使用 Viper 來管理配置

    Go語言如何使用 Viper 來管理配置

    在現(xiàn)代軟件開發(fā)中,良好的配置管理可以極大地提升應(yīng)用的靈活性和可維護(hù)性,下面我們就來看看GO語言中如何使用 Viper 來管理配置吧
    2024-11-11
  • Golang通過包長(zhǎng)協(xié)議處理TCP粘包的問題解決

    Golang通過包長(zhǎng)協(xié)議處理TCP粘包的問題解決

    本文主要介紹了Golang通過包長(zhǎng)協(xié)議處理TCP粘包的問題解決,文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2022-06-06
  • Go1.18新特性對(duì)泛型支持詳解

    Go1.18新特性對(duì)泛型支持詳解

    這篇文章主要為大家介紹了Go1.18新特性對(duì)泛型支持詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪
    2022-06-06
  • 深入理解Golang中的Protocol Buffers及其應(yīng)用

    深入理解Golang中的Protocol Buffers及其應(yīng)用

    本篇文章將深入探討 Go 語言中使用 Protobuf 的基礎(chǔ)知識(shí)、常見應(yīng)用以及最佳實(shí)踐,希望能幫大家了解如何在項(xiàng)目中高效利用 Protobuf
    2024-11-11

最新評(píng)論

海阳市| 崇明县| 西贡区| 迁西县| 汕尾市| 汾阳市| 扶绥县| 大埔区| 衡山县| 枣阳市| 安塞县| 天津市| 额尔古纳市| 德格县| 鹤庆县| 高台县| 和政县| 历史| 西丰县| 抚顺市| 普陀区| 南汇区| 抚州市| 桐城市| 蛟河市| 石景山区| 平罗县| 岢岚县| 漾濞| 麻江县| 永顺县| 颍上县| 彭水| 泾阳县| 广丰县| 柳林县| 都匀市| 海安县| 印江| 昌乐县| 乐亭县|