[LevelDB/源碼]Batch結(jié)構(gòu)分析

1.Batch的日常使用

batch的日常使用比較簡單,使用Batch是提高leveldb寫入性能的一個關(guān)鍵。

    db, _ := leveldb.OpenFile("file", nil)
    batch := leveldb.Batch{}
    batch.Put([]byte("k1"), []byte("y"))
    batch.Delete([]byte("k1"))
    db.Write(&batch, nil)

本文將結(jié)合batch的內(nèi)部結(jié)構(gòu)分析Put、Delete等操作的相關(guān)原理。

2.Batch的內(nèi)部結(jié)構(gòu)

db實(shí)例內(nèi)部擁有一個batch的對象池,batchPool, 在常規(guī)的db.put操作中,實(shí)際數(shù)據(jù)也是插入到batch 中的:

    batch := db.batchPool.Get().(*Batch)
    batch.Reset()
    batch.appendRec(kt, key, value)
    return db.writeLocked(batch, batch, merge, sync)

使用batchPool的方式減少了batch對象的開銷,batch的結(jié)構(gòu)定義如下

type Batch struct {
    data  []byte
    index []batchIndex
    // internalLen is sums of key/value pair length plus 8-bytes internal key.
    internalLen int
}

batch使用一個byte數(shù)組存儲具體數(shù)據(jù),這里data存儲實(shí)際的key和value值。batchIndex用于data內(nèi)部的key,value的索引
Batch內(nèi)部數(shù)據(jù)結(jié)構(gòu)圖示如下:

圖1. batch internal datastructure.png
type batchIndex struct {
    keyType            keyType //key的類型 插入或者刪除
    keyPos, keyLen     int //key的起始位置及其長度
    valuePos, valueLen int //value的起始長度以及其長度
}

3.Batch的關(guān)鍵函數(shù)

3.1 appendRec 數(shù)據(jù)插入函數(shù)

該內(nèi)部函數(shù)是Batch的Put以及Delete函數(shù)的內(nèi)部實(shí)現(xiàn),Put或者Delete以key的類型進(jìn)行區(qū)分。
batch的data部分存儲key和value的長度,主要是為了decodeBatch的方便。

func (b *Batch) appendRec(kt keyType, key, value []byte) {
    //1.計算存儲kt keylen  key valuelen value的data所需要的長度
    n := 1 + binary.MaxVarintLen32 + len(key)
    if kt == keyTypeVal {
        n += binary.MaxVarintLen32 + len(value)
    }

    //容量不足時及時擴(kuò)充容量
    b.grow(n)

    index := batchIndex{keyType: kt}
    o := len(b.data)
    data := b.data[:o+n] //更新slice, 即增加了data的實(shí)際length
    data[o] = byte(kt)   // o位置加上標(biāo)識位 占8位
    o++
    //序列化key值的長度并存儲到data內(nèi),key最長不超過32位
    o += binary.PutUvarint(data[o:], uint64(len(key)))
    index.keyPos = o
    index.keyLen = len(key) //記錄key的位置以及長度值

    o += copy(data[o:], key) //寫入key
    if kt == keyTypeVal {
        o += binary.PutUvarint(data[o:], uint64(len(value)))
        index.valuePos = o
        index.valueLen = len(value)
        o += copy(data[o:], value) //寫入value 返回copy的長度
    }
    b.data = data[:o]
    b.index = append(b.index, index)                   //添加一個batch索引項
    b.internalLen += index.keyLen + index.valueLen + 8 //內(nèi)部batch的長度 key value長度再加上8位的標(biāo)識位
}

3.2 grow 擴(kuò)容函數(shù)

func (b *Batch) grow(n int) {
    o := len(b.data)
    if cap(b.data)-o < n {
        div := 1
        if len(b.index) > batchGrowRec { //3000
            div = len(b.index) / batchGrowRec
        }
        ndata := make([]byte, o, o+n+o/div)
              //當(dāng)batch index很多的時候,擴(kuò)容的擴(kuò)充容量越小
              //batch index < batchGrowRec時擴(kuò)充為 2*old cap + n的新長度
        copy(ndata, b.data)
        b.data = ndata
    }
}
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

  • Spring Cloud為開發(fā)人員提供了快速構(gòu)建分布式系統(tǒng)中一些常見模式的工具(例如配置管理,服務(wù)發(fā)現(xiàn),斷路器,智...
    卡卡羅2017閱讀 136,697評論 19 139
  • 1. Java基礎(chǔ)部分 基礎(chǔ)部分的順序:基本語法,類相關(guān)的語法,內(nèi)部類的語法,繼承相關(guān)的語法,異常的語法,線程的語...
    子非魚_t_閱讀 34,853評論 18 399
  • Spark SQL, DataFrames and Datasets Guide Overview SQL Dat...
    草里有只羊閱讀 18,564評論 0 85
  • 轉(zhuǎn)至元數(shù)據(jù)結(jié)尾創(chuàng)建: 董瀟偉,最新修改于: 十二月 23, 2016 轉(zhuǎn)至元數(shù)據(jù)起始第一章:isa和Class一....
    40c0490e5268閱讀 2,101評論 0 9
  • 求起點(diǎn)到其他所有點(diǎn)的最短距離: Bellman_Ford算法 Dijkstra 最大網(wǎng)絡(luò)流算法 Edmonds_K...
    yingtaomj閱讀 301評論 0 1

友情鏈接更多精彩內(nèi)容