RocksDB dump 文件格式全解析:ROCKDUMP 二进制布局、dump/undump 工具与实战
2026/9/19 10:58:27 网站建设 项目流程

RocksDB dump 文件格式全解析:ROCKDUMP 二进制布局、dump/undump 工具与实战

【免费下载链接】rocksdbA library that provides an embeddable, persistent key-value store for fast storage.项目地址: https://gitcode.com/gh_mirrors/ro/rocksdb

本篇技术指南以仓库根目录下的 DUMP_FORMAT.md 为核心,系统讲解 RocksDB 逻辑备份文件(dump 文件)的 v1 二进制格式:从 8 字节魔数ROCKDUMP、大端版本号,到 4 字节小端长度前缀的 chunk 结构、首块 JSON 元信息,以及后续成对出现的 key/value 记录。结合 tools/dump/db_dump_tool.cc 的读写实现与 include/rocksdb/db_dump_tool.h 的公共接口,读者将掌握 dump 文件的字节级布局、rocksdb_dump/rocksdb_undump命令行工具的使用方法,以及如何自行解析或生成该格式。

一、dump 格式的定位:逻辑备份而非物理备份

RocksDB 的正常数据文件(SST、WAL、MANIFEST 等)内部布局复杂且与具体版本实现强相关,直接拷贝数据库目录进行备份通常要求版本兼容。而 dump 格式则是一种与数据库文件格式解耦的逻辑备份:它通过迭代器把数据库中的 key/value 对按顺序导出为一个顺序读写的流式文件,同时将数据库路径、主机名、创建时间等元信息以 JSON 形式保存在文件头部,使得任何平台、任何版本都能按同一套字节布局读出数据。

从 tools/dump/db_dump_tool.cc 的实现看,导出的数据源自DB::OpenForReadOnly打开数据库后创建的Iterator,以SeekToFirst()开始顺序遍历全部键值对;而恢复方向则由 DbUndumpTool::Run 逐条db->Put写入新库。因此 dump 文件本质上是一条"键值对 + 元信息"的自描述字节流,这正是 DUMP_FORMAT.md 所描述的 v1 格式。

二、v1 dump 文件字节级布局

根据 DUMP_FORMAT.md 的定义,v1 格式整体结构如下:

+---------------------------+---------------------------+-------------------------------+-----------------------------+---------------------+ | 魔数 "ROCKDUMP" (8 字节) | 版本号 (8 字节, 大端) | 信息块长度 (4 字节, 小端) | 信息块 JSON (长度不定) | key/value 记录序列 | +---------------------------+---------------------------+-------------------------------+-----------------------------+---------------------+

各组成部分详细说明:

  1. 魔数(Magic):文件以 8 字节 ASCII 标识符ROCKDUMP开头,用于快速识别文件是否为 RocksDB dump 文件。在 tools/dump/db_dump_tool.cc 中定义为static const char* magicstr = "ROCKDUMP";,实际写入时构造Slice(magicstr, 8)精确追加 8 字节。

  2. 版本号(Version):魔数之后是 8 字节**大端序(big-endian)**的格式版本号,v1 固定为0x00000001。对应源码中的static const char versionstr[8] = {0, 0, 0, 0, 0, 0, 0, 1};(tools/dump/db_dump_tool.cc)。大端序意味着多字节整数的最高有效字节在前,读取端只需按字节比对即可校验版本。

  3. Chunk 化长度前缀:从第三部分开始,文件由若干"长度前缀 + 数据"的 chunk 组成。每个 chunk 先写入4 字节小端序(little-endian)的长度值(uint32_t),随后紧跟该长度的原始字节。这一"小端长度 + 数据"的模式贯穿信息块与所有键值对。写入端使用 util/coding.h 中的EncodeFixed32uint32_t编码为固定 4 字节小端,读取端用DecodeFixed32还原。

  4. 首个 chunk 为 JSON 信息块:第一个 chunk 的数据是描述 dump 创建信息的 JSON 字符串,具体键如下:

键名含义
database-path被 dump 数据库的路径(写入时会通过Env::GetAbsolutePath转换为绝对路径)
hostname创建 dump 时所在机器的主机名(来自Env::GetHostName
creation-time创建 dump 的 Unix 秒级时间戳(来自Env::GetCurrentTime

对应实现见 tools/dump/db_dump_tool.cc,生成出的 JSON 形如:

{ "database-path": "/data/db", "hostname": "build-server-1", "creation-time": 1720000000 }
  1. 键值对序列:信息块之后,文件包含任意数量的键值对记录,每条记录是两个连续 chunk:先写入 4 字节小端 key 长度 + key 原始字节,再写入 4 字节小端 value 长度 + value 原始字节。写入端按it->key()/it->value()Slice大小动态生成长度前缀(tools/dump/db_dump_tool.cc)。文件到达末尾即自然结束,没有显式的结束标记。

一个完整文件的十六进制示意

以 key 为hello、value 为world的极简库为例,dump 文件字节流大致为:

52 4F 43 4B 44 55 4D 50 # "ROCKDUMP" 魔数 00 00 00 00 00 00 00 01 # 大端版本号 1 XX XX XX XX # 信息块长度(小端,4 字节) { "database-path": ... } # JSON 信息块 05 00 00 00 # key 长度 = 5(小端) 68 65 6C 6C 6F # "hello" 05 00 00 00 # value 长度 = 5(小端) 77 6F 72 6C 64 # "world"

注意观察两种整数序并存的设计:版本号使用大端,而所有 chunk 长度前缀使用小端。解析器必须区分对待,混用任一端的字节序都会导致数据错位。

三、写入与读取的源码实现印证

3.1 写入端:DbDumpTool::Run

导出流程位于 tools/dump/db_dump_tool.cc,关键步骤为:

  • 以只读方式打开源库:DB::OpenForReadOnly(options, dump_options.db_path, &db),并强制create_if_missing = false,防止误建新库;
  • 通过Env::Default()NewWritableFile创建 dump 输出文件;
  • 依次追加魔数、版本号、长度前缀 + JSON 信息块;
  • 创建Iterator顺序遍历,对每个有效键值对分别追加 key 长度、key、value 长度、value;
  • 遍历结束后检查it->status()确认迭代过程无错误。

值得注意的细节是anonymous选项:当DumpOptions::anonymous为真时(见 include/rocksdb/db_dump_tool.h),JSON 信息块被替换为{},从而隐去数据库路径、主机名与创建时间,适用于需要脱敏导出的场景。

3.2 读取端:DbUndumpTool::Run

导入流程位于 tools/dump/db_dump_tool.cc,关键校验与步骤:

  • 使用NewSequentialFile打开 dump 文件,先读取 8 字节与magicstr比对,不匹配则报is not a recognizable dump file
  • 再读取 8 字节与versionstr比对,不匹配则报version not recognized
  • 读取 4 字节信息块长度,Skip(infosize)跳过整个 JSON 信息块(读取端不解析 JSON 内容,仅跳过);
  • create_if_missing = true打开目标库,随后循环读取[key 长度][key][value 长度][value],逐条db->Put写入;
  • 当读到文件末尾(Read返回不足 4 字节)时正常结束循环,视作文件结束。

读取端还包含一个实用的内存优化:last_keysize/last_valsize从初始值(64 字节 key、1 MB value)开始,遇更大记录时按 2 倍扩容重新分配缓冲区(tools/dump/db_dump_tool.cc),避免对大 key/value 频繁 realloc。

3.3 公共接口

工具类的公共接口定义在 include/rocksdb/db_dump_tool.h:

  • DumpOptionsdb_path(源库路径)、dump_location(dump 输出文件路径)、anonymous(是否隐藏头部元信息);
  • DbDumpTool::Run(DumpOptions, Options):执行导出;
  • UndumpOptionsdb_path(目标库路径)、dump_location(dump 文件路径)、compact_db(导入完成后是否执行CompactRange压缩全库);
  • DbUndumpTool::Run(UndumpOptions, Options):执行导入。

其中compact_db在 tools/dump/db_dump_tool.cc 中通过db->CompactRange(CompactRangeOptions(), nullptr, nullptr)实现,可在加载后立即整理 LSM 结构,优化后续读性能。

四、命令行工具使用实战

仓库提供两个基于 gflags 的命令行可执行文件:

  • tools/dump/rocksdb_dump.cc:导出工具,参数为--db_path--dump_location--anonymous--db_options
  • tools/dump/rocksdb_undump.cc:导入工具,参数为--dump_location--db_path--compact--db_options

两者均要求 gflags 支持(util/gflags_compat.h),未安装 gflags 时程序会提示Please install gflags to run rocksdb tools。若--db_path--dump_location为空,工具会直接报错退出。

4.1 导出数据库为 dump 文件

./rocksdb_dump --db_path=/path/to/source/db --dump_location=/tmp/backup.dmp

导出过程以只读方式打开源库,不影响线上读写。若希望脱敏(不记录路径、主机名与时间):

./rocksdb_dump --anonymous --db_path=/path/to/source/db --dump_location=/tmp/backup.dmp

如需以特定选项打开源库,可追加--db_options,例如:

./rocksdb_dump --db_path=/path/to/source/db \ --dump_location=/tmp/backup.dmp \ --db_options="max_open_files=5000;write_buffer_size=67108864"

--db_options使用GetOptionsFromString解析(见 tools/dump/rocksdb_dump.cc),格式为key1=value1;key2=value2,适用于打开需要特殊配置(如不同压缩、不同块缓存)的数据库。

4.2 从 dump 文件恢复数据库

./rocksdb_undump --dump_location=/tmp/backup.dmp --db_path=/path/to/new/db

导入时会自动创建目标库(create_if_missing = true)。恢复后立即执行全库压缩:

./rocksdb_undump --dump_location=/tmp/backup.dmp \ --db_path=/path/to/new/db --compact

同样支持--db_options指定目标库的打开选项。

4.3 编译与测试验证

两个工具在构建系统中分别注册于 src.mk 与 tools/CMakeLists.txt。Makefile 提供了对应目标:

make rocksdb_dump rocksdb_undump

仓库自带回归测试脚本 tools/rocksdb_dump_test.sh,其验证思路与格式完全对应:

./rocksdb_undump --dump_location=tools/sample-dump.dmp --db_path=$TESTDIR/db ./rocksdb_dump --anonymous --db_path=$TESTDIR/db --dump_location=$TESTDIR/dump cmp tools/sample-dump.dmp $TESTDIR/dump

流程为:先用仓库内的样例 dump 文件tools/sample-dump.dmp还原出一个库,再以--anonymous重新导出,最后cmp逐字节比对,验证"还原→再导出"后内容完全一致(由于 anonymous 模式信息块固定为{},两次文件字节完全相同)。执行入口为make rocksdb_dump_test(见 Makefile)。

五、格式要点总结与兼容性注意事项

  • 整数字节序不对称:版本号为 8 字节大端;所有 chunk 长度前缀(信息块长度、key 长度、value 长度)均为 4 字节小端;
  • 长度前缀上限:长度字段为uint32_t,单个 key 或 value 不得超过 4 GiB,实际使用中远小于此;
  • 无结束标记:文件以键值对序列自然收尾,解析器依据"读不到完整 4 字节长度"判定 EOF;
  • 信息块为纯元数据:读取端只按长度跳过 JSON 而不解析,即使 JSON 内容为空(anonymous模式)也不影响数据加载;
  • 迭代序即存储序:导出顺序为数据库迭代器的顺序(按键有序),因此 dump 天然保序,但该顺序对恢复结果无影响(恢复是逐条 Put);
  • 版本演进:魔数与版本号双校验机制为未来格式演进留有余地,新版本可更新versionstr并保持向后兼容读取。

六、自行实现解析器的核对清单

若需要脱离 RocksDB 工具自行读取 dump 文件(如导入其他存储系统),按以下步骤校验即可:

  1. 读取前 8 字节,必须等于 ASCIIROCKDUMP
  2. 读取后 8 字节,当前仅接受大端值0x00000001
  3. 读取 4 字节小端n1,随后跳过n1字节的 JSON 元信息;
  4. 循环读取 4 字节小端kl,读取kl字节 key;再读取 4 字节小端vl,读取vl字节 value;
  5. 任一读取不足预期字节数即视为文件结束或损坏。

遵循上述布局即可完整还原 dump 内容;而生成 dump 时只需按"魔数 + 版本号 + 信息块 + 键值对序列"的顺序写出,即可被rocksdb_undumpDbUndumpTool正常识别和加载,实现跨工具的数据互通。

【免费下载链接】rocksdbA library that provides an embeddable, persistent key-value store for fast storage.项目地址: https://gitcode.com/gh_mirrors/ro/rocksdb

创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询