欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

go內(nèi)存緩存BigCache實(shí)現(xiàn)BytesQueue源碼解讀

 更新時(shí)間:2023年09月05日 15:35:12   作者:海生  
這篇文章主要為大家介紹了go內(nèi)存緩存BigCache實(shí)現(xiàn)BytesQueue源碼解讀,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪

一、BytesQueue結(jié)構(gòu)

BytesQueue結(jié)構(gòu),是bigcache真正數(shù)據(jù)存儲(chǔ)的地方。

值得注意的是刪除緩存元素的時(shí)候bigcache只是在map[uint64]uint32中刪除了它的索引,byte數(shù)組里的空間是不會(huì)釋放的。

在 bigCache 中,所有的 value 都是存在一個(gè) BytesQueue 中的,從實(shí)現(xiàn)可知,所有的用戶(hù)存儲(chǔ)數(shù)據(jù)經(jīng)由序列化后存入 array []byte

// BytesQueue is a non-thread safe queue type of fifo based on bytes array.
// BytesQueue 是基于字節(jié)數(shù)組的非線程安全隊(duì)列類(lèi)型的FIFO。
// For every push operation index of entry is returned. It can be used to read the entry later
// 對(duì)于每個(gè)推送操作索引,都會(huì)返回。它可用于稍后閱讀條目。
type BytesQueue struct {
    full         bool
    array        []byte // 真正存儲(chǔ)數(shù)據(jù)的地方
    capacity     int    // array 的容量
    maxCapacity  int    // array 可申請(qǐng)的最大容量
    head         int
    tail         int // 下次可以插入 item 的位置
    count        int // 當(dāng)前插入的 item 數(shù)量
    rightMargin  int
    headerBuffer []byte // 插入前做臨時(shí) buffer 所用(slice-copy)
    verbose      bool   // 打印 log 開(kāi)關(guān)
}

初始化BytesQueue方法

func NewBytesQueue(capacity int, maxCapacity int, verbose bool) *BytesQueue {
    return &BytesQueue{
        array:        make([]byte, capacity), // 真正存儲(chǔ)數(shù)據(jù)的地方,長(zhǎng)度為capacity,直接初始化每個(gè)值
        capacity:     capacity,
        maxCapacity:  maxCapacity,
        headerBuffer: make([]byte, binary.MaxVarintLen32),
        tail:         leftMarginIndex,
        head:         leftMarginIndex,
        rightMargin:  leftMarginIndex,
        verbose:      verbose,
    }
}

我們通過(guò)維護(hù)下面幾個(gè)變量來(lái)實(shí)現(xiàn)存儲(chǔ)位移及標(biāo)識(shí):

head:起始位置(也可以理解為,當(dāng)前最老的數(shù)據(jù)的位置,刪除的邏輯從這個(gè)位置開(kāi)始)

tail:下次可以插入 item 的位置

capacity:標(biāo)識(shí) array 的容量

count:當(dāng)前已經(jīng)插入的 item 的數(shù)量

maxCapacity:標(biāo)識(shí) array 可以申請(qǐng)的最大容量

rightMargin:用于標(biāo)識(shí)隊(duì)列中最后一個(gè)元素的位置,是一個(gè)絕對(duì)位置。

leftMarginIndex:常量,值為 1,標(biāo)識(shí)隊(duì)列的開(kāi)頭位置(0 號(hào)不用)

注意, head 和 tail 以及 rightMargin 的初始值都是 leftMarginIndex。BytesQueue 使用 []byte 類(lèi)型來(lái)模擬隊(duì)列,插入數(shù)據(jù)從 tail 位置,刪除數(shù)據(jù)從 head 位置。為標(biāo)準(zhǔn)的FIFO隊(duì)列。

二、如何使用這個(gè)BytesQueue

1、插入item到隊(duì)列,通過(guò)調(diào)用BytesQueue.Push([]byte) 方法,我們可以把[]byte類(lèi)型的數(shù)據(jù)插入到BytesQueue中。

返回為這個(gè)值存儲(chǔ)的index索引。

func TestQueuePush(t *testing.T) {
    // 初始化一個(gè)byte隊(duì)列
    queue := NewBytesQueue(5, 0, false)
    t.Log(queue) // &{false [0 0 0 0 0] 5 0 1 1 0 1 [0 0 0 0 0] false}
    // 調(diào)用Push方法,會(huì)返回獲取這個(gè)值的index索引
    index, err := queue.Push([]byte("a"))
    t.Log(index, err) // 1 <nil>
    index, err = queue.Push([]byte("b"))
    t.Log(index, err) // 3 <nil>
    // 通過(guò)index索引就可以獲取到這個(gè)值
    a, err2 := queue.Get(1)
    t.Log(string(a), err2) // a <nil>
    b, err2 := queue.Get(3)
    t.Log(string(b), err2) // b <nil>
}

這樣,我們就相當(dāng)于一個(gè)值,和一個(gè)索引index對(duì)應(yīng)了。

通過(guò)一個(gè)索引可以快速的獲取到這個(gè)值。

bigcache我們通過(guò)BytesQueue,存儲(chǔ)數(shù)據(jù)。

再用一個(gè)map,記錄一下這個(gè)index和值的 對(duì)應(yīng)關(guān)系。

就可O(1)的時(shí)間復(fù)雜度,查詢(xún)BytesQueue的所有數(shù)據(jù)。

-----注意:為什么通過(guò)index可以獲取value的值?

因?yàn)槲覀冊(cè)賞ush的 []byte的時(shí)候,最終存儲(chǔ)這個(gè)[]byte會(huì)用一個(gè)8字節(jié)存儲(chǔ)這個(gè)entry的長(zhǎng)度。

這樣通過(guò)index我們獲取到這個(gè)長(zhǎng)度,然后就可以獲取到這個(gè)數(shù)據(jù)。

func (q *BytesQueue) Push(data []byte) (int, error) {
    neededSize := getNeededSize(len(data))
    ....... // 省略
    index := q.tail

    q.push(data, neededSize)

    return index, nil
}

從Push()方法中,我們看到調(diào)用了一個(gè)push()方法。我們打開(kāi)源代碼,可以看到最終在保存數(shù)據(jù)的時(shí)候,先用一個(gè)8字節(jié)保存了 data的長(zhǎng)度。

func (q *BytesQueue) push(data []byte, len int) {
    headerEntrySize := binary.PutUvarint(q.headerBuffer, uint64(len))
    q.copy(q.headerBuffer, headerEntrySize) // 用一個(gè)8字節(jié)保存data的長(zhǎng)度
    q.copy(data, len-headerEntrySize)       // 寫(xiě)入data
    if q.tail > q.head {
        q.rightMargin = q.tail
    }
    if q.tail == q.head {
        q.full = true
    }
    q.count++
}

byteQueue中每個(gè)元素都有2部分組成,前8個(gè)byte是數(shù)據(jù)的長(zhǎng)度,后面是數(shù)據(jù)的值本身,每個(gè)byteQueue中每個(gè)元素的最大長(zhǎng)度是8個(gè)字節(jié),2的64次方。

以上就是go內(nèi)存緩存BigCache實(shí)現(xiàn)BytesQueue源碼解讀的詳細(xì)內(nèi)容,更多關(guān)于go內(nèi)存緩存BigCache BytesQueue的資料請(qǐng)關(guān)注腳本之家其它相關(guān)文章!

相關(guān)文章

  • Go??iota?常量基本語(yǔ)法介紹

    Go??iota?常量基本語(yǔ)法介紹

    這篇文章主要介紹了Go?為什么要設(shè)計(jì)?iota?常量,我們介紹了 Go 中 iota 的基本語(yǔ)法。同時(shí)基于歷史資料針對(duì) iota 到底是什么,為什么要這么叫,又有什么用進(jìn)行了一番研究,需要的朋友可以參考下
    2022-06-06
  • golang?struct?json?tag的使用以及深入講解

    golang?struct?json?tag的使用以及深入講解

    這篇文章主要給大家介紹了關(guān)于golang?struct?json?tag的使用以及深入講解,文中通過(guò)實(shí)例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友可以參考下
    2022-02-02
  • go語(yǔ)言異常panic和恢復(fù)recover用法實(shí)例

    go語(yǔ)言異常panic和恢復(fù)recover用法實(shí)例

    這篇文章主要介紹了go語(yǔ)言異常panic和恢復(fù)recover用法,實(shí)例分析了異常panic和恢復(fù)recover使用技巧,具有一定參考借鑒價(jià)值,需要的朋友可以參考下
    2015-03-03
  • Go項(xiàng)目與Docker結(jié)合實(shí)現(xiàn)高效部署深入探究

    Go項(xiàng)目與Docker結(jié)合實(shí)現(xiàn)高效部署深入探究

    在現(xiàn)代軟件開(kāi)發(fā)中,使用Docker部署應(yīng)用程序已經(jīng)成為一種標(biāo)準(zhǔn)實(shí)踐,本文將深入探討如何將Go項(xiàng)目與Docker結(jié)合,實(shí)現(xiàn)高效、可靠的部署過(guò)程,通過(guò)詳細(xì)的步驟和豐富的示例,你將能夠迅速掌握這一流程
    2023-12-12
  • Golang的func參數(shù)及返回值操作

    Golang的func參數(shù)及返回值操作

    這篇文章主要介紹了Golang的func參數(shù)及返回值操作,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過(guò)來(lái)看看吧
    2021-05-05
  • go語(yǔ)言操作之nacos配置中心

    go語(yǔ)言操作之nacos配置中心

    這篇文章主要介紹了go語(yǔ)言操作之nacos配置中心,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教
    2023-06-06
  • Golang中的time.Duration類(lèi)型用法說(shuō)明

    Golang中的time.Duration類(lèi)型用法說(shuō)明

    這篇文章主要介紹了Golang中的time.Duration類(lèi)型用法說(shuō)明,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過(guò)來(lái)看看吧
    2020-12-12
  • go數(shù)據(jù)結(jié)構(gòu)和算法BitMap原理及實(shí)現(xiàn)示例

    go數(shù)據(jù)結(jié)構(gòu)和算法BitMap原理及實(shí)現(xiàn)示例

    這篇文章主要為大家介紹了go數(shù)據(jù)結(jié)構(gòu)和算法BitMap原理及實(shí)現(xiàn)示例,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪
    2022-07-07
  • 重學(xué)Go語(yǔ)言之文件操作詳解

    重學(xué)Go語(yǔ)言之文件操作詳解

    有很多場(chǎng)景都需要對(duì)文件進(jìn)行讀取或者寫(xiě)入,比如讀取配置文件或者寫(xiě)入日志文件,在Go語(yǔ)言中,操作文件應(yīng)該算是一件比較簡(jiǎn)單的事情,我們?cè)谶@一篇文章中,一起來(lái)探究一下
    2023-08-08
  • 關(guān)于golang?struct?中的?slice?無(wú)法原子賦值的問(wèn)題

    關(guān)于golang?struct?中的?slice?無(wú)法原子賦值的問(wèn)題

    這篇文章主要介紹了為什么?golang?struct?中的?slice?無(wú)法原子賦值的問(wèn)題,本文給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下
    2024-01-01

最新評(píng)論