leveldb源码分析—Recover和Repair
时间:2022-03-10 18:16
leveldb作为一个KV存储引擎将数据持久化到磁盘,而对于一个存储引擎来说在存储过程中因为一些其他原因导致程序down掉甚至数据文件被破坏等都会导致程序不能按正常流程再次启动。那么遇到这些状况以后如何使程序最大程度的恢复数据就是非常重要的一项工作,leveldb也提供了这方面的工作。
首先来看recover,这是每一次启动数据库的时候都会呗调用到的流程。其功能是恢复数据库在运行中突然因为某些原因down掉而这个时候leveldb中的丢失的当前状态,以及memtable甚至immtable中还未持久化到SSTable中的数据。我们知道leveldb采用的是WAL的方式进行的,那么对于leveldb中的当前状态存储在manifest文件中,通过读取已经持久化的状态,然后在结合WAL总的信息就可以恢复到最新状态;而memtable和immtable中的数据恢复的主要就是将未持久化到SSTable的数据从Log中读取出来重做到memtable或者SSTable即可。整个恢复的流程如下:
恢复了当前version的基本信息以后进行日志操作就可以恢复内存中的数据了,重做日志操作即是将日志中记录的操作读取出来,然后再将读取到的操作重新写入到leveldb中
void RepairTable(const std::string& src, TableInfo t) { // 遍历SSTable生成新的SSTable,并删除旧的 // 生成新文件 std::string copy = TableFileName(dbname_, next_file_number_++); WritableFile* file; Status s = env_->NewWritableFile(copy, &file); if (!s.ok()) { return; } TableBuilder* builder = new TableBuilder(options_, file); // Copy data. Iterator* iter = NewTableIterator(t.meta); int counter = 0; for (iter->SeekToFirst(); iter->Valid(); iter->Next()) { builder->Add(iter->key(), iter->value()); counter++; } delete iter; ArchiveFile(src); //将旧文件移到lost下 if (counter == 0) { builder->Abandon(); // Nothing to save } else { s = builder->Finish(); if (s.ok()) { t.meta.file_size = builder->FileSize(); } } delete builder; builder = NULL; if (s.ok()) { s = file->Close(); } delete file; file = NULL; if (counter > 0 && s.ok()) { std::string orig = TableFileName(dbname_, t.meta.number); s = env_->RenameFile(copy, orig); if (s.ok()) { tables_.push_back(t); } } if (!s.ok()) { env_->DeleteFile(copy); } }
在recover和repair的过程中我们发现了version的维护和管理十分重要,原本不打算再对这部分进行分析,但是现在看来对其进行一下细致的梳理还是很有必要的,预计下一篇专门介绍这部分内容。
leveldb源码分析—Recover和Repair,布布扣,bubuko.com