【原创】HPB之go leveldb数据库的Put操作源码


#1

之前的leveldb总结分享中说到了三个关键部分,数据的Put,Get,compaction。其中put操作实现了数据的增删改功能,Get操作实现了数据的查功能。本文从源码角度说明下put操作的相关流程。

put接口位于leveldb的db_write.go文件中,代码如下

func (db *DB) Put(key, value []byte, wo *opt.WriteOptions) error {`

​    return db.putRec(keyTypeVal, key, value, wo)

}

Put接口下面就是Delete接口,代码如下

 func (db *DB) Delete(key []byte, wo *opt.WriteOptions) error {
    ​    return db.putRec(keyTypeDel, key, nil, wo)
    }

其中put接口与delete接口都是通过调用db.putrec函数实现的,不同的地方在于,put操作的数据属性为keyTypeVal,表示数据有效,是插入数据,delete操作的数据属性为keyTypeDel,表示数据无效,是删除数据。接下来看db.putRec是如何实现的。下面代码只保留了流程关键部分。

func (db *DB) putRec(kt keyType, key, value []byte, wo *opt.WriteOptions) error 

   ......省略代码.......

​    batch := db.batchPool.Get().(*Batch)

​    batch.Reset()

​    batch.appendRec(kt, key, value)

​    return db.writeLocked(batch, batch, merge, sync)

}

将keytype,key,value放入batch中,调用db.writeLocked函数

func (db *DB) writeLocked(batch, ourBatch *Batch, merge, sync bool) error {

​    mdb, mdbFree, err := db.flush(batch.internalLen)

​     ............省略代码...........

​    if err := db.writeJournal(batches, seq, sync); err != nil {

​        db.unlockWrite(overflow, merged, err)

​        return err

​    }

​    // Put batches.

​    for _, batch := range batches {

​        if err := batch.putMem(seq, mdb.DB); err != nil {

​            panic(err)

​        }

​        seq += uint64(batch.Len())

​    }

   ...................

​    db.unlockWrite(overflow, merged, nil)

​    return nil

}

从上述代码可以看出关键流程只有3步,flush,writeJournal,putMem。

其中flush主要是为了申请内存用于存储数据,

writeJournal主要是为了将数据写入log文件,用于系统异常时恢复数据,避免数据丢失。

putMem则是将数据写入flush申请的内存。

至此,一次写入操作就完成了。至于后面将内存的数据写入到磁盘上,就属于memcomcaption的地盘了。

leveldb的Put操作原理是很简单的,将数据写入log,因为是顺序追加,还是很快的,将数据写入内存那就更快了。这也就是leveldb写操作快的原因。


#2

看你这这个标题,看来是打算写成系列作品啊

建议可以这么起名字: ”HPB源码解读系列之LevelDB的put操作解析“

下一篇是xxxxx解析一类的名字,如何?