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

1.Batch的日常使用

batch的日常使用比較簡(jiǎn)單,使用Batch是提高leveldb寫入性能的一個(gè)關(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)部擁有一個(gè)batch的對(duì)象池,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對(duì)象的開(kāi)銷,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使用一個(gè)byte數(shù)組存儲(chǔ)具體數(shù)據(jù),這里data存儲(chǔ)實(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的起始位置及其長(zhǎng)度
    valuePos, valueLen int //value的起始長(zhǎng)度以及其長(zhǎng)度
}

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部分存儲(chǔ)key和value的長(zhǎng)度,主要是為了decodeBatch的方便。

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

    //容量不足時(shí)及時(shí)擴(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)識(shí)位 占8位
    o++
    //序列化key值的長(zhǎng)度并存儲(chǔ)到data內(nèi),key最長(zhǎng)不超過(guò)32位
    o += binary.PutUvarint(data[o:], uint64(len(key)))
    index.keyPos = o
    index.keyLen = len(key) //記錄key的位置以及長(zhǎng)度值

    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的長(zhǎng)度
    }
    b.data = data[:o]
    b.index = append(b.index, index)                   //添加一個(gè)batch索引項(xiàng)
    b.internalLen += index.keyLen + index.valueLen + 8 //內(nèi)部batch的長(zhǎng)度 key value長(zhǎng)度再加上8位的標(biāo)識(shí)位
}

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

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

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

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