Leveldb 解读之三:Write
这一篇我们来分析 leveldb 的 write,写流程相对比较简单。
Write 流程
流程说明:
使用 WriteBatch 封装要写入的多个 kv,然后调用 push 到 writebatch 队列。
多个写线程在 writebatch 队列上等待,等到任务执行完毕(被其他 writer 捎带执行),或者任务排到了队列头部,可以开始执行。
写过程首先调用 MakeRoomForWrite 准备 Memtable 表,然后从 writebatch 队列中出队一批写任务,打包一起执行。
执行过程很简单,标准 WAL 写法,先写 log,再写 memtable,适当的时候把 memtable 刷盘。
MakeRoomForWrite
如果当前 Memtable < write_buffer_size(缺省是 4M),则什么都不做,继续使用当前 Memtable。
否则,关闭当前 Memtable(改为 imm)和 log 文件,切换到新的 Memtable 和 log 文件。
写操作的原子性
写操作使用 WriteBatch 封装一批要写入的 kv,然后打包成一条记录写入 log 文件,MemTable 是逐个 key 插入的,但只是中间状态(不会失败,但是对其他 Reader 可见,不满足隔离性)。因此,使用 WriteBatch 写入/删除多个 key 是原子操作。
持久性
leveldb 支持同步写,设置 wirte_option.sync,写操作在调用 log->append()操作后,会调用 logfile->Sync(),等待操作系统把文件缓存刷入硬盘,但同步写性能比较差。
在 leveldb 的官方文档里面也提到了,一般情况下,异步写完全够用,
Memtable
Memtable 使用的 skiplist 是线程安全的,支持一读多写并发,这对读写并发度高的业务非常友好。
Sequence
在 leveldb 中使用 sequence 序号来实现 key 值版本管理和 snapshot。在 Memtable 中,key 的格式是:
在写入 sstable file 时,也是按这个格式编码,但会对 user_key 进行前缀压缩。
评论