[LevelDB] LevelDB之WriteBatch

1. LevelDB的写数据

在leveldb中,我们通过调用db->Put(WriteOptions(),&key,&value);来写入数据,而WriteOptions只有一个变量sync,且默认初始值为false,因此leveldb默认的写数据方式是异步,即每将写操作提交将数据写入到内存中就返回,而将数据从内存写到磁盘的方式是异步的。

异步写比同步写的效率高得多,但是当系统故障时,可能导致最近的更新丢失。若将WriteOptions的sync设为true,则每次写入都会将数据写入到磁盘中,速度非常慢。

为此leveldb使用WriteBatch来替代简单的异步写操作,首先将所有的写操作记录到一个batch中,然后执行同步写,这样同步写的开销就被分散到多个写操作中。

利用leveldb的WriteBatch可以进行批量处理,用法如下:

leveldb::WriteBatch batch;
batch.Put(key1, value1);
batch.Delete(key1);
batch.Put(key2, value);
s = db->Write(leveldb::WriteOptions(), &batch);
即使没有显式使用batch,在调用DB::Put()时,也是将一条记录通过WriteBatch的形式存储到系统中的

2. WriteBatch

WriteBatch的原理是先将所有的操作记录下来,然后再一起操作。

由之前的分析可知,leveldb插入和删除数据并不是直接插入、删除数据,而是插入一条记录(由记录的标志位来确定是要插入数据还是删除数据,具体的插入、删除操作将在Compaction时进行)
因此WriteBatch将会记录许多个操作,每一个操作代表着要插入或删除相应数据。

WriteBatch类的定义如下:

 


每一个WriteBatch都是以一个固定长度的头部开始,然后后面接着许多连续的记录,
固定头部共12字节,其中前8字节为WriteBatch的序列号,对应rep_[0]到rep_[7],每次处理Batch中的记录时才会更新,后四字节为当前Batch中的记录数,对应rep_[8]到rep_[11];

通过头部我们就可以知道每一个batch的序号了,并能够知道每一个batch中的记录数,将batch写入到文件中后就可以方便的依次获取每一条记录了。

后面的记录结构为:
插入数据时:type(kTypeValue、kTypeDeletion),Key_size,Key,Value_size,Value
删除数据时:type(kTypeValue、kTypeDeletion),Key_size,Key

3. WriteBatch的基本操作

WriteBatch的基本操作是记录一个要插入或删除某个数据的操作,最基本的操作就是Put和Delete

Put:将一条要插入数据的操作写入到rep_中

void WriteBatch::Put(const Slice& key, const Slice& value) {

WriteBatchInternal::SetCount(this, WriteBatchInternal::Count(this) + 1);  //操作总数加1
rep_.push_back(static_cast<char>(kTypeValue));            //写入操作类型
PutLengthPrefixedSlice(&rep_, key);                  //写入key.size()和key.data()
PutLengthPrefixedSlice(&rep_, value);                  //写入value.size()和value.data()

}


Delete:将一条要删除数据的操作写入到rep_中

void WriteBatch::Delete(const Slice& key) {
      WriteBatchInternal::SetCount(this, WriteBatchInternal::Count(this) + 1); //操作总数加1
      rep_.push_back(static_cast<char>(kTypeDeletion));          //写入操作类型
      PutLengthPrefixedSlice(&rep_, key);                   //写入待删除数据的key值
}


4. 基本示例

WriteBatch wb;
wb.Put("key1","hello");
wb.Put("key2","hi");
wb.Delete("key1");


执行上面的代码后,WriteBatch中的rep_如下:

10000000 3000 (前8位为序列号,从1开始,后4位为操作数,共3个操作)
0 4 k e y 1 5 h e l l o (第一个操作,0表示要插入数据)
0 4 k e y 2 2 h i (第二个操作)
1 4 k e y 1 (第三个操作,1表示要删除数据)
共39位
---------------------
作者:禾夕
来源:CSDN
原文:https://blog.csdn.net/u012658346/article/details/45341885
版权声明:本文为博主原创文章,转载请附上博文链接!

猜你喜欢

转载自www.cnblogs.com/mh1092/p/9934399.html