leveldb的写操作大致分两步:
- 写日志文件并持久化。
- 写日志成功之后再写入到内存中的memtable。
整个写操作都是顺序的,所以leveldb写速度很快。
那leveldb写日志文件并持久化的目的是什么呢?这就涉及到我们今天讨论的数据还原。
先把数据写入到日志文件,如果leveldb异常退出了,下次启动时可以从日志文件中恢复需要写的KV数据。
那leveldb能保证进行写的数据不丢失吗?答案是不完全,来看下leveldb写入一条数据的大致流程:
从流程中我们可以分析出哪些数据可恢复、哪些数据恢复不了。
无法恢复
数据还未写入到logfile,即数据还在leveldb的缓存或者系统的cache层,这个时候如果掉电或者leveldb异常退出,这些数据是丢失无法恢复的,但是掉电数据丢失的概率更大。
可以恢复
数据已写入到logfile,如果设备掉电或者leveldb异常退出,这些数据在leveldb再次启动时通过DBImpl::Recover()
流程可正常恢复。
说完了哪些数据可恢复之后,接下来说下恢复流程。
大致流程如下:
源码比较简单,基本都已在流程图中体现出来了,这里就不走读了。
总结
这里有几点需要下:
- 一个内存Memtable对应一个logfile,但新建一个Memtable时,也会伴随创建一个新的logfile。
- 在Compact Memtable之后,会删除掉无用的logfile,此时如果删除时leveldb异常退出了,没关系,下次进行Memtable时会删除之前旧的无用的logfile。
- 若memtable已生存好,准备将logfile记录写入到manifest中时,此时leveldb异常退出,那在下次打开leveldb时会进行Recover,对logfile进行还原生存一个SSTable文件,这个SSTable顶多是和之前已存在的SSTable重复了,不过没关系,生成的SSTable都是在leveldb-0层,在往leveldb-1及以上层进行Compact时会去掉重复的数据。