![8e856eb5f569069384a5c5453a8963f0.png](https://img-blog.csdnimg.cn/img_convert/8e856eb5f569069384a5c5453a8963f0.png)
写操作
写操作是LevelDB着重强调的性能提升点。一般的数据库采用B+树,当在没有随机写的情况下,B+树的性能还是令人满意的。但面对大量随机写时,B+树会分裂,插入的Key值跨度会非常大,导致需要大量磁盘I/O。而LevelDB采用LSM树的思想,将随机写变为顺序写从而提升性能。
LevelDB提供了三个和写操作相关的接口。
- DBImpl::Put: 增加或修改一个KV记录。
- DBImpl::Delete: 删除一条kv记录。
Put和Delete操作完全相同,只是在写入时record的类型不同。Put和Delete对应的Key-Value直接写入即可,后续compaction会进行处理。
默认情况下,为了保证性能,LevelDB采用异步写操作。当LevelDB把写操作提交给数据库后立刻返回,之后异步的将操作应用到数据库中,将其持久化。异步写通常比同步写速度快数百倍以上,但存在当及其宕机时丢失更新数据的问题。同时,LevelDB采用批量写方法,可以减少平均每次写入操作的磁盘开销。
我们从DBImpl的入口函数开始阅读LevelDB写入相关的代码。
http://db_impl.cc
对外接口
LevelDB对外的写操作接口为:
Status DBImpl::Put(const WriteOptions& o, const Slice& key, const Slice& val) {
return DB::Put(o, key, val);
}
Status DBImpl::Delete(const WriteOptions& options, const Slice& key) {
return DB::Delete(options, key);
}
- DBImple中的成员函数直接通过调用父类的成员函数实现。
- WriteOptions为写操作参数,当前只有一个成员变量
sync
,表示每次写操作是否需要立刻将数据同步到磁盘,默认为异步写入。
调用DB中的成员函数,二者都通过封装的 Write
函数是实现。
virtual Status Write(const WriteOptions& options, WriteBatch* updates) = 0;
Status DB::Put(const WriteOptions& opt, const Slice& key, const Slice& value) {
WriteBatch batch;
batch.Put(key, value); // 将Key-Value加入WriteBatch中
return Write(opt, &batch); // 传入Batch,调用Write函数
}
Status DB::Delete(const WriteOptions& opt, const Slice& key) {
WriteBatch batch;
batch.Delete(key);
return Write(opt, &batch);
}
- LevelDB采用