-
Notifications
You must be signed in to change notification settings - Fork 6
SidePlugin Java Binding
只需要 Bind SidePluginRepo
,并且只需要 bind 极少的方法(此处仅列出声明):
class SidePluginRepo extends RocksObject {
public SidePluginRepo(); // constructor
public void importAutoFile(String fname) throws RocksDBException;
public RocksDB openDB(String js) throws RocksDBException;
public RocksDB openDB(String js, List<ColumnFamilyHandle> out_cfhs);
public RocksDB openDB() throws RocksDBException;
public RocksDB openDB(List<ColumnFamilyHandle> out_cfhs) throws RocksDBException;
public void startHttpServer() throws RocksDBException;
public void closeHttpServer();
public void closeAllDB(); // conform to C++ native name CloseAllDB
public void close(); // synonym to closeAllDB
public void put(String name, String spec, Options opt); // rarely used
public void put(String name, String spec, DBOptions dbo); // rarely used
public void put(String name, String spec, ColumnFamilyOptions cfo); // rarely used
}
这么小的工作量,我已经多年没碰过 java,jni 更是从来没用过,实现这个 Binding,现学现卖,从头至尾,也只花了不到一天的时间。所以,良好的架构设计,可以极大地减小工作量,如果按照 SidePlugin 的架构,rocksdbjava 中的代码(java 代码与 c++ 各约 4 万行)至少可以缩减 90%。
参考 C++ 版的 101,Java 版的写法没啥大的不同;再参考实际的例子 SideGetBenchmarks,相信大家很容易使用 java 调用 ToplingDB。
其中的 put
方法是为了兼容已有代码:如果现存代码对各种 Option 进行了一些设置,并且这些设置无法通过配置文件进行配置(例如自定义了 java 版的 CompactionFilter),就先把 option put 到 SidePluginRepo
,然后再调用 importAutoFile —— importAutoFile 会补充 put option 中的缺失选项,并覆盖同名选项!
git clone https://github.com/topling/toplingdb.git --depth 1
cd toplingdb
git submodule update --init --recursive
ssh-keyscan -t rsa github.com >> ~/.ssh/known_hosts # silent git
make -j`nproc` DEBUG_LEVEL=0 shared_lib
sudo make install-shared PREFIX=/opt
make rocksdbjava -j`nproc` DEBUG_LEVEL=0
你现在应该位于 toplingdb 仓库的根目录
cd java/target
cp rocksdbjni-7.10.0-linux64.jar rocksdbjni-7.10.0-SNAPSHOT-linux64.jar
mvn install:install-file -Dfile=rocksdbjni-7.10.0-SNAPSHOT-linux64.jar -DgroupId=org.rocksdb -DartifactId=rocksdbjni -Dversion=7.10.0-SNAPSHOT -Dpackaging=jar
假定你现在位于 toplingdb 仓库的根目录
cd java/jmh
mvn clean package
假定你现在已经位于 toplingdb/java/jmh
mkdir -p /dev/shm/db_bench_enterprise
cp ../../sideplugin/rockside/src/topling/web/{style.css,index.html} /dev/shm/db_bench_enterprise
export LD_LIBRARY_PATH=/opt/lib:$LD_LIBRARY_PATH # for libterark-*
export LD_PRELOAD=libterark-zbs-g++-12.1-r.so:libterark-fsa-g++-12.1-r.so:libjemalloc.so
java -jar target/rocksdbjni-jmh-1.0-SNAPSHOT-benchmarks.jar \
-p keyCount=1000 -p keySize=128 -p valueSize=32768 \
-p sideConf=../../sideplugin/rockside/sample-conf/db_bench_enterprise.yaml SideGetBenchmarks
运行起来之后,可以访问 http://127.0.0.1:2011 观测 db 状态。
说明 1:社区版用户请将 db_bench_enterprise.yaml 替换为 db_bench_community.yaml,这两个文件都在 toplingdb
/sideplugin/rockside/sample-conf 中, sideplugin/rockside 是 ToplingDB 的 submodule。
说明 2:设置 LD_PRELOAD 是因为 toplingdb 和 jemalloc 动态库使用了 init exec 类型的 TLS(线程局部存储),这种 TLS 访问速度最快,但使用了这种 TLS 的动态库必须预先加载,或者由可执行文件显式链接。而 java 加载 jni 是由 jvm 动态加载的,如果不用 LD_PRELOAD,会导致动态库中的这种 TLS 初始化失败。
目前使用 Java 实现的组件无法用 Java 代码注册到 SidePlugin 的插件库中,一般情况下这并不是什么严重问题,唯一的问题在于:无法使用分布式 Compact。
例如在 Java 中实现了自定义的 CompactionFilter/MergeOperator ,因为无法注册到 SidePlugin 的插件库中,所以无法为 dcompact_worker 预加载相应的动态库以运行分布式 Compact。除非(1)实现专门的动态库,在其中用 jni 创建 JVM 并调用 Java 代码,并创建 C++ 包装类,把相应的组件注册到 SidePlugin 中。或者(2)使用 C++ 实现相同功能的插件并注册到 SidePlugin 中,例如数据都是 protobuf 格式,用 C++ 实现相应插件并不困难,而且性能还更高。