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类的定义如下:
![](https://img2018.cnblogs.com/blog/1532638/201811/1532638-20181109122621949-90668052.png)
每一个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
版权声明:本文为博主原创文章,转载请附上博文链接!