RocksDB 修复者
概述
Repairer尽最大努力在不损害一致性的情况下恢复灾难后尽可能多的数据。它不能保证使数据库达到时间一致的状态。 注:目前有一个限制,un-flushed 未刷新列族将丢失后修复。即使数据库处于健康状态,也会发生这种情况。
使用
注意,CLI命令使用默认选项来修复数据库,并且只添加在SST文件中找到的列族。 如果需要指定任何选项,例如自定义比较器、具有特定于列族的选项,或者希望指定列族的确切集合,则应该选择编程方式。
Programmatic 有计划的
对于编程使用,调用include/rocksdb/db.h中声明的一个RepairDB函数。
CLI 命令行
对于CLI的使用,首先构建ldb,我们的管理CLI工具:
$ make clean && make ldb
现在使用ldb的repair子命令指定您的DB。 注意,它将信息日志打印到stderr,因此您可能希望重定向。 这里我在DB ./tmp中运行它,我已经删除了 MANIFEST 文件:
$ ./ldb repair --db=./tmp 2>./repair-log.txt
$ tail -2 ./repair-log.txt
[WARN] [db/repair.cc:208] **** Repaired rocksdb ./tmp; recovered 1 files; 926bytes. 一些数据可能已经丢失。 ****
看起来是成功的。返回MANIFEST文件,DB可读:
$ ls tmp/
000006.sst CURRENT IDENTITY LOCK LOG LOG.old.1504116879407136 lost MANIFEST-000001 MANIFEST-000003 OPTIONS-000005
$ ldb get a --db=./tmp
b
注意lost/目录。它保存包含在恢复期间可能丢失的数据的文件。
修复过程
修复过程分为4个阶段:
- 找到文件
- 将日志转换为表
- 提取元数据
- 写描述符
Find files 找到文件
修复程序遍历目录中的所有文件,并根据它们的文件名对它们进行分类。任何不能通过名称标识的文件都将被忽略。
Convert logs to table 将日志转换为表
每个活动的日志文件都会重新播放。跳过校验和不匹配的文件的所有部分。我们有意地优先考虑数据一致性。
Extract metadata 提取元数据
我们扫描每一张表来计算
- smallest/largest 表
- 表中最大的序号
如果无法扫描文件,则忽略该表。
Write Descriptor 写描述符
我们生成描述符内容:
- 日志号设置为零
- 下一个文件号设置为1 +我们找到的最大文件号
- last-sequence-number被设置为可以在所有表中找到的最大序列#
- 清除压缩指针
- 每个表文件都是在第0级添加的
Possible optimization 可能的优化
1.计算总大小并用于选择合适的最大级别M 2.按表中最大的序列#对表进行排序 3.对于每个表: 如果它与前面的表重叠,则将其放置在级别0中,否则将其放置在级别m中。 4.我们可以为时间一致的恢复和不安全的恢复提供选项(在适用时忽略校验和失败) 5.在表的元数据部分中存储每个表的元数据(最小、最大、最大-seq#,…),以加快ScanTable的速度。
限制
如果列族是最近创建的,并且没有通过刷新保存在sst文件中,那么它将在修复过程中被删除。 有了这个限制,如果它的列族还没有被刷新,修复甚至可能会损害健康的数据库。