RocksDB 修复者

概述

Repairer尽最大努力在不损害一致性的情况下恢复灾难后尽可能多的数据。它不能保证使数据库达到时间一致的状态。 注:目前有一个限制,un-flushed 未刷新列族将丢失后修复。即使数据库处于健康状态,也会发生这种情况。

使用

注意,CLI命令使用默认选项来修复数据库,并且只添加在SST文件中找到的列族。 如果需要指定任何选项,例如自定义比较器、具有特定于列族的选项,或者希望指定列族的确切集合,则应该选择编程方式。

Programmatic 有计划的

对于编程使用,调用include/rocksdb/db.h中声明的一个RepairDB函数。

CLI 命令行

对于CLI的使用,首先构建ldb,我们的管理CLI工具:

  1. $ make clean && make ldb

现在使用ldb的repair子命令指定您的DB。 注意,它将信息日志打印到stderr,因此您可能希望重定向。 这里我在DB ./tmp中运行它,我已经删除了 MANIFEST 文件:

  1. $ ./ldb repair --db=./tmp 2>./repair-log.txt
  2. $ tail -2 ./repair-log.txt
  3. [WARN] [db/repair.cc:208] **** Repaired rocksdb ./tmp; recovered 1 files; 926bytes. 一些数据可能已经丢失。 ****

看起来是成功的。返回MANIFEST文件,DB可读:

  1. $ ls tmp/
  2. 000006.sst CURRENT IDENTITY LOCK LOG LOG.old.1504116879407136 lost MANIFEST-000001 MANIFEST-000003 OPTIONS-000005
  3. $ ldb get a --db=./tmp
  4. 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文件中,那么它将在修复过程中被删除。 有了这个限制,如果它的列族还没有被刷新,修复甚至可能会损害健康的数据库。