RocksDB 插件机制与第三方插件生态全指南:从官方插件清单到构建系统源码解析
【免费下载链接】rocksdbA library that provides an embeddable, persistent key-value store for fast storage.项目地址: https://gitcode.com/gh_mirrors/ro/rocksdb
RocksDB 是一款可嵌入、持久化的键值存储引擎,其强大的可定制性不仅体现在丰富的配置项上,还体现在一套面向开发者的插件(Plugin)机制中:第三方开发者可以通过插件接口扩展 Env、文件系统、加密等能力,并随 RocksDB 一起编译进同一个二进制。本文以仓库根目录下的官方插件清单 PLUGINS.md 为主体,结合 plugin/README.md 的插件构建标准与 Makefile、CMakeLists.txt 中的实际实现,系统梳理已知第三方插件生态、插件目录组织规范、make/CMake 双构建系统的接入方式,以及静态注册的底层原理,帮助你快速上手"发现插件 → 接入构建 → 理解注册机制"的完整链路。
一、官方插件清单(PLUGINS.md)解读:已知的第三方插件生态
仓库根目录下的 PLUGINS.md 是 RocksDB 官方维护的第三方插件总清单,其定位是"让用户能够方便地发现和复用他人定制 RocksDB 的解决方案"。文档明确说明:如果你的插件尚未收录,可以通过 Pull Request 补充到该清单。截至当前仓库版本,清单共收录 7 个插件,按功能领域可划分为四类。
1. 示例插件:Dedupfs
Dedupfs是一个去重文件系统插件,官方在清单中明确标注其双重身份:既是真实可用的插件,更是供插件开发者参考的标准示例。plugin/README.md 在"Example"一节同样以 Dedupfs 作为唯一的工作示例(working example),下文第三、四节中的目录组织与构建变量规范均以它为准。对于想开发第一个插件的开发者,Dedupfs 是必须研读的模板。
2. 环境抽象(Env)类插件:HDFS 与 RADOS
RocksDB 通过Env抽象层屏蔽底层文件系统差异,因此对接分布式存储最自然的做法就是实现一个自定义 Env:
- HDFS:用于与 Hadoop HDFS 交互的
Env实现,由 RocksDB 主仓库迁移而来,适合把 RocksDB 部署在 Hadoop 生态存储之上的场景。 - RADOS:用于与 Ceph RADOS 对象存储交互的
Env实现,同样迁移自 RocksDB 主仓库,适合依赖 Ceph 集群的部署环境。
这两类插件说明:迁移自主仓库的代码也是插件生态的重要组成部分,用户无需改动 RocksDB 核心即可获得额外存储后端支持。
3. 存储介质类插件:ZenFS 与 PMEM
针对新型存储介质,插件机制让 RocksDB 能适配特殊设备:
- ZenFS:面向**分区块设备(zoned block devices)**的文件系统实现,使 RocksDB 可以运行在 ZNS SSD 等分区存储设备上,通过顺序写特性提升寿命与吞吐。
- PMEM:一个插件集合,用于在 RocksDB 上启用持久内存(Persistent Memory,如 Intel Optane 持久内存),让持久化与内存访问路径更贴合 NVM 硬件特性。
4. 加密类插件:IPPCP 与 encfs
- IPPCP:基于 Intel 优化开源 IPP-Crypto 库的加密插件,为 RocksDB 提供加密能力。
- encfs:基于 OpenSSL 库的加密插件,同样用于启用 RocksDB 的加密功能。
值得注意的是,include/rocksdb/env_encryption.h 等加密相关接口与
EncryptedEnv这类实现共同构成了 RocksDB 加密体系的基座,上述两个加密插件正是围绕这一体系构建的Env封装,这也解释了为何加密能力可以通过"插件"而非"核心代码"的方式扩展。
二、插件机制的设计初衷:外部代码与 RocksDB 联合构建
在深入构建细节前,先理解 plugin/README.md 阐述的核心设计。RocksDB 为开发者提供了多种插件接口用于定制行为(Env、文件系统、Table 工厂等),但开发者面临的真正困难是:如何让最终用户方便地使用自己的插件。
当前官方推荐的方案是——把外部插件代码与 RocksDB 代码一起编译进单个二进制(building the external code together with the RocksDB code into a single binary)。文档同时提到另一条规划中的路线:从共享库动态加载插件(loading plugins dynamically from shared libraries),后者尚未落地,因此本文聚焦于当前唯一受支持的联合构建方式。
同时,plugin/README.md 明确把PLUGINS.md 清单与插件发现机制绑定:官方希望开发者将作品记录在 PLUGINS.md 中,让用户能轻松发现并复用各种定制方案。这解释了为何仓库既有 PLUGINS.md(面向用户的清单)又有 plugin/README.md(面向开发者的构建标准)。
三、插件目录组织与双构建系统接入规范
3.1 目录组织规范
外部插件按名称链接(link)到plugin/的子目录中。例如名为dedupfs的插件,会被链接到plugin/dedupfs/。当前仓库的 plugin/ 目录下只保留了 README.md 本身,并没有内置任何插件源码——插件目录由开发者各自维护,构建时按名链接进来。
3.2 支持范围:make 与 CMake
plugin/README.md 明确:目前唯一受支持的构建系统是make 和 cmake两套。下面分别说明二者约定的构建变量。
3.3 Make 构建标准(.mk文件)
对于 make,plugin/<name>/目录下以.mk结尾的文件可定义以下变量:
| 变量 | 作用 |
|---|---|
$(PLUGIN_NAME)_SOURCES | 这些源文件将被编译并链接进 RocksDB,可以访问 RocksDB 公共头文件 |
$(PLUGIN_NAME)_HEADERS | 这些头文件将被安装到 RocksDB 头文件目录,路径以rocksdb/plugin/$(PLUGIN_NAME)/为前缀 |
$(PLUGIN_NAME)_LDFLAGS | 传递给最终链接步骤的链接标志,可用于传播库依赖,或强制包含符号(例如用于静态注册) |
$(PLUGIN_NAME)_CXXFLAGS | 传递给编译器的编译标志,例如指定非标准位置的头文件路径 |
3.4 CMake 构建标准(CMakeLists.txt)
对于 CMake,插件目录下的CMakeLists.txt可定义以下变量:
| 变量 | 作用 |
|---|---|
${PLUGIN_NAME}_SOURCES | 将被编译并链接进 RocksDB 的源文件,可访问 RocksDB 公共头文件 |
${PLUGIN_NAME}_COMPILE_FLAGS | 传递给编译器的标志,例如指定非标准头文件位置 |
${PLUGIN_NAME}_INCLUDE_PATHS | 编译期间搜索插件专属头文件的目录列表 |
${PLUGIN_NAME}_LIBS | 构建插件所需链接的库名列表,如dl、java、jvm、rados等,CMake 会据此生成正确链接标志 |
${PLUGIN_NAME}_LINK_PATHS | 除标准位置外,链接器搜索所需库的路径列表 |
${PLUGIN_NAME}_CMAKE_SHARED_LINKER_FLAGS | 生成共享库时使用的附加链接标志,例如强制包含符号以支持静态注册 |
${PLUGIN_NAME}_CMAKE_EXE_LINKER_FLAGS | 生成可执行文件时使用的附加链接标志,同样可用于强制包含符号 |
3.5 用户侧接入命令
用户无需关心插件内部实现,只需在构建时通过ROCKSDB_PLUGINS变量以空格分隔列表的形式声明要启用的插件:
- Make:从 RocksDB 目录执行常规 make 命令并追加变量:
make ROCKSDB_PLUGINS="dedupfs hdfs rados" -j$(nproc)- CMake:在调用 cmake 时通过命令行变量传入:
cmake .. -DROCKSDB_PLUGINS="dedupfs hdfs rados"两条命令一脉相承:构建系统会自动发现并链接对应插件,最终产出包含插件能力的 RocksDB 库与工具。
四、源码级解析:Makefile 中的插件接入实现
规范之外,真正验证插件机制的是构建系统的实际代码。查看仓库根目录 Makefile 可以还原 make 侧完整的处理流程。
4.1 插件.mk文件的发现与展开
ROCKSDB_PLUGIN_MKS = $(foreach plugin, $(ROCKSDB_PLUGINS), plugin/$(plugin)/*.mk) include $(ROCKSDB_PLUGIN_MKS)构建系统首先针对ROCKSDB_PLUGINS中的每个插件名,通配包含对应plugin/<name>/*.mk文件(Makefile)。随后逐一展开插件声明的各类变量:
ROCKSDB_PLUGIN_SOURCES = $(foreach p, $(ROCKSDB_PLUGINS), $(foreach source, $($(p)_SOURCES), plugin/$(p)/$(source))) ROCKSDB_PLUGIN_HEADERS = $(foreach p, $(ROCKSDB_PLUGINS), $(foreach header, $($(p)_HEADERS), plugin/$(p)/$(header))) ROCKSDB_PLUGIN_LIBS = $(foreach p, $(ROCKSDB_PLUGINS), $(foreach lib, $($(p)_LIBS), -l$(lib))) ROCKSDB_PLUGIN_LDFLAGS = $(foreach plugin, $(ROCKSDB_PLUGINS), $($(plugin)_LDFLAGS)) ROCKSDB_PLUGIN_TESTS = $(foreach p, $(ROCKSDB_PLUGINS), $(foreach test, $($(p)_TESTS), plugin/$(p)/$(test)))(见 Makefile)这些宏把插件源文件、头文件、链接库、链接标志、测试文件统一并入 RocksDB 的构建图:插件源文件与核心代码一起编译链接;插件头文件按rocksdb/plugin/<name>/前缀安装;_LIBS被转换为-l<lib>形式;_TESTS则并入测试目标(CMake 侧对应PLUGIN_TESTS,见 CMakeLists.txt)。
编译与链接标志的注入同样直接:
CXXFLAGS += $(foreach plugin, $(ROCKSDB_PLUGINS), $($(plugin)_CXXFLAGS)) PLATFORM_LDFLAGS += $(ROCKSDB_PLUGIN_LDFLAGS)(见 Makefile)插件声明的_CXXFLAGS追加到全局编译标志,_LDFLAGS追加到平台链接标志。
4.2 静态注册机制:从_FUNC到 ObjectRegistry
Make 标准之外,构建系统还支持一个关键约定——$(PLUGIN_NAME)_FUNC静态注册函数。其核心作用是让插件在库被加载时自动登记到 RocksDB 的ObjectRegistry,从而无需用户显式调用即可启用插件能力:
ROCKSDB_PLUGIN_W_FUNCS = $(foreach p, $(ROCKSDB_PLUGINS), $(if $($(p)_FUNC), $(p))) ROCKSDB_PLUGIN_EXTERNS = $(foreach p, $(ROCKSDB_PLUGIN_W_FUNCS), int $($(p)_FUNC)($(ROCKSDB_PLUGIN_PROTO));) ROCKSDB_PLUGIN_BUILTINS = $(foreach p, $(ROCKSDB_PLUGIN_W_FUNCS), {\"$(p)\"\, $($(p)_FUNC)}\,)(见 Makefile)其中ROCKSDB_PLUGIN_PROTO被定义为ROCKSDB_NAMESPACE::ObjectLibrary&, const std::string&(Makefile),即注册函数的签名。构建时生成的版本源文件 util/build_version.cc.in 会把这两个宏替换进去:
extern "C" { @ROCKSDB_PLUGIN_EXTERNS@ } // extern "C" std::unordered_map<std::string, ROCKSDB_NAMESPACE::RegistrarFunc> ROCKSDB_NAMESPACE::ObjectRegistry::builtins_ = { @ROCKSDB_PLUGIN_BUILTINS@ };(见 util/build_version.cc.in)替换由 Makefile 中的gen_build_version规则通过 sed 完成。可以看到:插件注册函数以extern "C"声明,并以{"插件名", 注册函数}的形式填入ObjectRegistry::builtins_映射——这是插件能被按名查找并实例化的底层桥梁,即 plugin/README.md 中"符号可被强制包含、用于静态注册"的实际落地。
4.3 pkg-config 依赖支持
对于依赖第三方系统库的插件(如加密插件依赖 OpenSSL、IPP-Crypto),Make 侧还预留了$(PLUGIN_NAME)_PKGCONFIG_REQUIRES变量,通过pkg-config自动展开头文件与链接标志:
LDFLAGS := $(LDFLAGS) $(shell pkg-config --libs $(ROCKSDB_PLUGIN_PKGCONFIG_REQUIRES)) ... CXXFLAGS := $(CXXFLAGS) $(shell pkg-config --cflags $(ROCKSDB_PLUGIN_PKGCONFIG_REQUIRES))(见 Makefile)若pkg-config调用失败(.SHELLSTATUS非 0),构建会直接报错终止,避免静默产出残缺链接结果。
五、源码级解析:CMake 侧的两段式处理
CMake 侧的实现分为用户变量解析与.mk兼容解析两段,见 CMakeLists.txt 与 CMakeLists.txt。
5.1 第一段:CMake 原生插件变量
if ( ROCKSDB_PLUGINS ) string(REPLACE " " ";" PLUGINS ${ROCKSDB_PLUGINS}) foreach (plugin ${PLUGINS}) add_subdirectory("plugin/${plugin}") foreach (src ${${plugin}_SOURCES}) list(APPEND SOURCES plugin/${plugin}/${src}) set_source_files_properties( plugin/${plugin}/${src} PROPERTIES COMPILE_FLAGS "${${plugin}_COMPILE_FLAGS}") endforeach() ... foreach (lib ${${plugin}_LIBS}) list(APPEND THIRDPARTY_LIBS ${lib}) endforeach() foreach (link_path ${${plugin}_LINK_PATHS}) link_directories(AFTER ${link_path}) endforeach() set(CMAKE_SHARED_LINKER_FLAGS "...${${plugin}_CMAKE_SHARED_LINKER_FLAGS}") set(CMAKE_EXE_LINKER_FLAGS "...${${plugin}_CMAKE_EXE_LINKER_FLAGS}") endforeach() endif()(见 CMakeLists.txt)流程要点:将空格分隔的ROCKSDB_PLUGINS转为列表;通过add_subdirectory("plugin/${plugin}")引入插件自己的CMakeLists.txt;_SOURCES、_TESTS、_INCLUDE_PATHS、_LIBS、_LINK_PATHS与两类链接器标志依次并入主构建。其中插件测试统一追加到PLUGIN_TESTS,最终进入测试目标(CMakeLists.txt)。
5.2 第二段:兼容解析.mk文件(_FUNC静态注册)
CMake 同时兼容 Make 侧的.mk约定:对每个插件检查plugin/<name>/<name>.mk是否存在,缺失则FATAL_ERROR(CMakeLists.txt);随后用正则解析其中的SOURCES = ...、_FUNC = ...、_LIBS = ...:
string(REGEX MATCH "_FUNC = ([^\n]*)" FOO ${PLUGINMK}) if (NOT ${CMAKE_MATCH_1} STREQUAL "") string(APPEND ROCKSDB_PLUGIN_BUILTINS "{\"${PLUGIN}\", " ${CMAKE_MATCH_1} "},") string(APPEND ROCKSDB_PLUGIN_EXTERNS "int " ${CMAKE_MATCH_1} "(ROCKSDB_NAMESPACE::ObjectLibrary&, const std::string&); ") endif()(见 CMakeLists.txt)与 Make 侧一样,解析出的_FUNC被注入 util/build_version.cc.in 的ObjectRegistry::builtins_初始化列表,实现插件的静态登记。CMakeLists.txt 中message(STATUS "ROCKSDB PLUGINS TO BUILD ${ROCKSDB_PLUGINS}")(CMakeLists.txt)会在配置阶段打印出本次构建包含的插件列表,便于排查。
六、Java 侧插件支持:JNI 源文件与测试的接入
RocksDB 的 Java 绑定同样支持插件: java/Makefile 中,构建系统从../plugin(即仓库根plugin/)按名包含插件.mk,并额外支持插件提供 Java 源码与测试:
PLUGIN_PATH = ../plugin ROCKSDB_PLUGIN_MKS = $(foreach plugin, $(ROCKSDB_PLUGINS), $(PLUGIN_PATH)/$(plugin)/*.mk) include $(ROCKSDB_PLUGIN_MKS) ROCKSDB_PLUGIN_JAVA_ROOTS = $(foreach plugin, $(ROCKSDB_PLUGINS), $(PLUGIN_PATH)/$(plugin)/java) PLUGIN_SOURCES = $(foreach root, $(ROCKSDB_PLUGIN_JAVA_ROOTS), $(foreach pkg, org/rocksdb/util org/rocksdb, $(root)/$(MAIN_SRC)/$(pkg)/*.java))(见 java/Makefile)插件根目录下的java/子树按org/rocksdb等包路径并入主源码与测试集合;此外还支持插件自定义原生 Java 类与测试:
ROCKSDB_PLUGIN_NATIVE_JAVA_CLASSES = $(foreach plugin, $(ROCKSDB_PLUGINS), $(foreach class, $($(plugin)_NATIVE_JAVA_CLASSES), $(class))) ROCKSDB_PLUGIN_JAVA_TESTS = $(foreach plugin, $(ROCKSDB_PLUGINS), $(foreach testclass, $($(plugin)_JAVA_TESTS), $(testclass)))(见 java/Makefile)而在主 Makefile 中,插件声明的_LDFLAGS会追加到 JNI 的JAVA_LDFLAGS/JAVA_STATIC_LDFLAGS,_JNI_NATIVE_SOURCES与_JNI_CXX_INCLUDEFLAGS则扩充 JNI 原生源文件与头文件搜索路径。这意味着一个插件可以同时交付 C++ 能力与 Java 绑定,覆盖 C++/JNI 双语言调用面。
七、开发实战:如何从零接入一个插件
结合 plugin/README.md 与上文源码分析,开发并接入一个插件的最小流程如下:
确定扩展点:根据需求选择 RocksDB 插件接口,例如自定义
Env(对接新文件系统/存储)、加密Env(基于EncryptedEnv体系)、Table/压缩器工厂等。可参考 include/rocksdb/env.h、include/rocksdb/env_encryption.h 等公共头文件确定接口签名。组织目录:将插件代码放入独立目录,命名为
plugin/<name>/,并在其中编写构建描述文件(make 用<name>.mk,CMake 用CMakeLists.txt)。若希望同时支持两套构建系统,可参考 CMake 对.mk的兼容解析,两者可并存。声明构建变量:在
.mk/CMakeLists.txt中按第三节的变量表声明_SOURCES、_HEADERS、_LIBS、_LDFLAGS/_CXXFLAGS(或 CMake 对应变量)。需要静态注册时,额外提供$(PLUGIN_NAME)_FUNC指定的int func(ROCKSDB_NAMESPACE::ObjectLibrary&, const std::string&)注册函数——该函数会被自动注入ObjectRegistry::builtins_,实现"库加载即注册"。联合构建验证:在 RocksDB 仓库根目录执行
make ROCKSDB_PLUGINS="<name>"或cmake .. -DROCKSDB_PLUGINS="<name>",确认编译链接通过;CMake 配置阶段会出现ROCKSDB PLUGINS TO BUILD <name>与PLUGIN <name> including ...日志(CMakeLists.txt),可作为验证依据。收录进官方清单:按 PLUGINS.md 的说明,通过 Pull Request 将插件名称与功能描述追加进清单,帮助其他用户发现你的成果——这也是官方推荐的插件分发与发现路径。
可选的 Java 支持:如需 Java 侧能力,在插件目录下提供
java/子树并声明_NATIVE_JAVA_CLASSES、_JAVA_TESTS等变量,随 java/Makefile 一并构建。
八、总结
RocksDB 的插件体系是一条"清单 + 构建规范 + 静态注册"三位一体的完整链路:PLUGINS.md 负责让用户发现插件(当前收录 Dedupfs、HDFS、ZenFS、RADOS、PMEM、IPPCP、encfs 七款,覆盖示例、分布式存储 Env、新型介质、加密四类场景);plugin/README.md 定义了 make 与 CMake 两套构建标准和plugin/<name>/目录组织;而 Makefile、CMakeLists.txt 与 util/build_version.cc.in 则从源码层面落实了源文件并入、链接标志传递、pkg-config依赖解析与ObjectRegistry::builtins_静态注册。理解了这三层,无论是直接使用现成插件、还是参照 Dedupfs 开发自己的定制能力,都能做到心中有数、开箱即用。
【免费下载链接】rocksdbA library that provides an embeddable, persistent key-value store for fast storage.项目地址: https://gitcode.com/gh_mirrors/ro/rocksdb
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考