本文主要記錄在利用 YCSB 使用配置文件測試 RocksDB 的過程中遇到的一些問題以及相應的解決辦法
簡介
YCSB 的全程是 Yahoo! Cloud Serving Benchmark,是雅虎開發的用來對雲服務進行基礎測試的工具,支持目前常見的 NoSQL 數據庫產品,如 HBase、MongoDB、OrientDB、Redis 等等
RocksDB 是一個具有鍵/值接口的存儲引擎,其中鍵和值是任意字節流。它是在 Facebook(Meta) 基於 LevelDB 開發的,並為 LevelDB API 提供向后兼容的支持
編譯 RocksDB
由於 YCSB 是用 Java 實現的,一般測試的數據庫都需要提供 Java 版本的 .jar
包
雖然 RocksDB 最初是 C++ 的一個庫(因為是嵌入式數據庫),但是后續也提供了 Java 的 API 以及可以通過源碼編譯出 .jar
包,也可以直接通過 Maven
獲取
官方在 GitHub 上給出了 Java 版本的介紹,編譯過程也很簡單
首先需要保證機器上安裝好了 Java 的環境,必須在 1.7+ 版本以上,例如,安裝 openjdk-8-jdk
包即可
sudo apt install openjdk-8-jdk
同時 RocksDB 本身還有一些環境需要安裝,官方 也給出來了
sudo apt-get install libgflags-dev libsnappy-dev zlib1g-dev libbz2-dev liblz4-dev libzstd-dev
實際編譯 jar 包時,需要提前配置好環境變量
export JAVA_HOME="/usr/lib/jvm/java-8-openjdk-amd64"
實際編譯時,有兩個中版本可以選擇,其中 rocksdbjava
是 debug 版本,而 rocksdbjavastatic
這是 release 版本,不過官方在 Java 版說明中沒有提及,我是在 Makefile 文件 中找到的
make -j$(nproc) rocksdbjava
make -j$(nproc) rocksdbjavastatic
編譯 YCSB
YCSB 在 2019/10/17 的 4a99009 增加了對 RocksDB 配置文件的支持,然而目前官方給出的 release 版本還是 0.17.0,並且發布時間是 2019/10/6,因此我們只能選擇從源碼開始編譯了
根據 官方給出的流程
git clone https://github.com/brianfrankcooper/YCSB.git
cd YCSB
mvn -pl site.ycsb:rocksdb-binding -am clean package
此時編譯好的文件在 ./rocksdb/target/
目錄下
~/YCSB$ ls rocksdb/target/*.jar
rocksdb/target/rocksdb-binding-0.18.0-SNAPSHOT.jar
該 .jar
包其實只是 YCSB 和 RocksDB 之間的中間件,實際使用的 RocksDB 的 .jar
包以及其他的依賴包則是在 ./rocksdb/target/dependency/
目錄下
~/YCSB$ tree rocksdb/target/dependency/
rocksdb/target/dependency/
├── jcip-annotations-1.0.jar
├── rocksdbjni-6.2.2.jar
├── slf4j-api-1.7.25.jar
└── slf4j-simple-1.7.25.jar
RocksDB 的包其實是由 YCSB 通過 Maven
下載的,具體的版本在 pom.xml 中定義了
- 如果使用原本 RocksDB 則可以簡單的通過修改這個版本信息,重新編譯利用
Maven
重新下載 - 如果使用的是自己修改過源碼的 RocksDB 則需要將自行編譯的 RocksDB 的
.jar
包移到該目錄下,並且刪除舊的.jar
包
修復報錯
但此時如果使用 ./bin/ycsb.sh
來進行測試,會報錯
~/YCSB$ ./bin/ycsb.sh load rocksdb -s -P workloads/workloada -p rocksdb.dir=tmp/
/usr/lib/jvm/java-8-openjdk-amd64/bin/java -classpath /home/ywang/YCSB/conf:/home/ywang/YCSB/core/target/core-0.18.0-SNAPSHOT.jar:/home/ywang/YCSB/rocksdb/target/rocksdb-binding-0.18.0-SNAPSHOT.jar:/home/ywang/YCSB/rocksdb/target/dependency/jcip-annotations-1.0.jar:/home/ywang/YCSB/rocksdb/target/dependency/rocksdbjni-6.2.2.jar:/home/ywang/YCSB/rocksdb/target/dependency/slf4j-api-1.7.25.jar:/home/ywang/YCSB/rocksdb/target/dependency/slf4j-simple-1.7.25.jar site.ycsb.Client -load -db site.ycsb.db.rocksdb.RocksDBClient -s -P workloads/workloada -p rocksdb.dir=tmp/
Command line: -load -db site.ycsb.db.rocksdb.RocksDBClient -s -P workloads/workloada -p rocksdb.dir=tmp/
YCSB Client 0.18.0-SNAPSHOT
Loading workload...
Exception in thread "main" java.lang.NoClassDefFoundError: org/apache/htrace/core/Tracer$Builder
at site.ycsb.Client.getTracer(Client.java:458)
at site.ycsb.Client.main(Client.java:304)
Caused by: java.lang.ClassNotFoundException: org.apache.htrace.core.Tracer$Builder
at java.net.URLClassLoader.findClass(URLClassLoader.java:387)
at java.lang.ClassLoader.loadClass(ClassLoader.java:418)
at sun.misc.Launcher$AppClassLoader.loadClass(Launcher.java:352)
at java.lang.ClassLoader.loadClass(ClassLoader.java:351)
... 2 more
(might take a few minutes for large data sets)
主要是使用的 ./bin/ycsb.sh
腳本有 bug,官方已經知道,並嘗試修復,不過好像仍然沒有解決
目前可以手動將 htrace
的包的依賴加入 RocksDB 中,並重新編譯,利用 Maven
下載到 ./rocksdb/target/dependency/
目錄下
可以手動將 ./core/pom.xml
中 htrace
的依賴信息復制添加到 ./rocksdb/pom.xml
中
<!-- ./rocksdb/pom.xml -->
……
<dependency>
<groupId>org.rocksdb</groupId>
<artifactId>rocksdbjni</artifactId>
<version>${rocksdb.version}</version>
</dependency>
<dependency>
<groupId>org.apache.htrace</groupId>
<artifactId>htrace-core4</artifactId>
<version>4.1.0-incubating</version>
</dependency>
<dependency>
<groupId>site.ycsb</groupId>
<artifactId>core</artifactId>
<version>${project.version}</version>
<scope>provided</scope>
</dependency>
……
然后利用 mvn -pl site.ycsb:rocksdb-binding -am clean package
重新編譯
這時再次利用 ./bin/ycsb.sh
來進行測試,還會報錯
~/YCSB$ ./bin/ycsb.sh load rocksdb -s -P workloads/workloada -p rocksdb.dir=tmp/
/usr/lib/jvm/java-8-openjdk-amd64/bin/java -classpath /home/ywang/YCSB/conf:/home/ywang/YCSB/core/target/core-0.18.0-SNAPSHOT.jar:/home/ywang/YCSB/rocksdb/target/rocksdb-binding-0.18.0-SNAPSHOT.jar:/home/ywang/YCSB/rocksdb/target/dependency/htrace-core4-4.1.0-incubating.jar:/home/ywang/YCSB/rocksdb/target/dependency/jcip-annotations-1.0.jar:/home/ywang/YCSB/rocksdb/target/dependency/rocksdbjni-6.2.2.jar:/home/ywang/YCSB/rocksdb/target/dependency/slf4j-api-1.7.25.jar:/home/ywang/YCSB/rocksdb/target/dependency/slf4j-simple-1.7.25.jar site.ycsb.Client -load -db site.ycsb.db.rocksdb.RocksDBClient -s -P workloads/workloada -p rocksdb.dir=tmp/
Command line: -load -db site.ycsb.db.rocksdb.RocksDBClient -s -P workloads/workloada -p rocksdb.dir=tmp/
YCSB Client 0.18.0-SNAPSHOT
Loading workload...
Starting test.
[Thread-3] INFO site.ycsb.db.rocksdb.RocksDBClient - RocksDB data dir: tmp
2021-12-25 16:10:30:807 0 sec: 0 operations; est completion in 0 second
DBWrapper: report latency for each error is false and specific error codes to track for latency are: []
Exception in thread "Thread-3" java.lang.NoClassDefFoundError: org/HdrHistogram/EncodableHistogram
at site.ycsb.measurements.Measurements.constructOneMeasurement(Measurements.java:129)
at site.ycsb.measurements.Measurements.getOpMeasurement(Measurements.java:220)
at site.ycsb.measurements.Measurements.measure(Measurements.java:188)
at site.ycsb.DBWrapper.measure(DBWrapper.java:184)
at site.ycsb.DBWrapper.insert(DBWrapper.java:229)
at site.ycsb.workloads.CoreWorkload.doInsert(CoreWorkload.java:621)
at site.ycsb.ClientThread.run(ClientThread.java:135)
at java.lang.Thread.run(Thread.java:748)
Caused by: java.lang.ClassNotFoundException: org.HdrHistogram.EncodableHistogram
at java.net.URLClassLoader.findClass(URLClassLoader.java:387)
at java.lang.ClassLoader.loadClass(ClassLoader.java:418)
at sun.misc.Launcher$AppClassLoader.loadClass(Launcher.java:352)
at java.lang.ClassLoader.loadClass(ClassLoader.java:351)
... 8 more
2021-12-25 16:10:30:954 0 sec: 0 operations; est completion in 106751991167300 days 15 hours
[OVERALL], RunTime(ms), 170
[OVERALL], Throughput(ops/sec), 0.0
[TOTAL_GCS_PS_Scavenge], Count, 0
[TOTAL_GC_TIME_PS_Scavenge], Time(ms), 0
[TOTAL_GC_TIME_%_PS_Scavenge], Time(%), 0.0
[TOTAL_GCS_PS_MarkSweep], Count, 0
[TOTAL_GC_TIME_PS_MarkSweep], Time(ms), 0
[TOTAL_GC_TIME_%_PS_MarkSweep], Time(%), 0.0
[TOTAL_GCs], Count, 0
[TOTAL_GC_TIME], Time(ms), 0
[TOTAL_GC_TIME_%], Time(%), 0.0
原因和之前一樣,再次將 HdrHistogram
相關的依賴,從 ./core/pom.xml
復制添加到 ./rocksdb/pom.xml
中
<!-- ./rocksdb/pom.xml -->
……
<dependency>
<groupId>org.rocksdb</groupId>
<artifactId>rocksdbjni</artifactId>
<version>${rocksdb.version}</version>
</dependency>
<dependency>
<groupId>org.apache.htrace</groupId>
<artifactId>htrace-core4</artifactId>
<version>4.1.0-incubating</version>
</dependency>
<dependency>
<groupId>org.hdrhistogram</groupId>
<artifactId>HdrHistogram</artifactId>
<version>2.1.4</version>
</dependency>
<dependency>
<groupId>site.ycsb</groupId>
<artifactId>core</artifactId>
<version>${project.version}</version>
<scope>provided</scope>
</dependency>
……
然后利用 mvn -pl site.ycsb:rocksdb-binding -am clean package
重新編譯
這時再次利用 ./bin/ycsb.sh
來進行測試就已經正常了
自定義配置 RocksDB 進行 YCSB 測試
自定義配置 RocksDB 的方式就很簡單了,在 YCSB 測試時增加 rocksdb.optionsfile
參數並給出配置文件的路徑即可
./bin/ycsb.sh load rocksdb -s -P workloads/workloada -p rocksdb.dir=/tmp/ycsb-rocksdb-data -p workloads/ycsb-rocksdb-options.ini
./bin/ycsb.sh run rocksdb -s -P workloads/workloada -p rocksdb.dir=/tmp/ycsb-rocksdb-data -p workloads/ycsb-rocksdb-options.ini
- 配置文件可以參考 RocksDB 官方的例子 修改
- 也可以先不加測試文件,執行一次
./bin/ycsb.sh load rocksdb -s -P workloads/workloada -p rocksdb.dir=/tmp/ycsb-rocksdb-data
,讓 YCSB 自己生成,然后根據 RocksDB 測試目錄(/tmp/ycsb-rocksdb-data
)下的OPTIONS-000009
的配置文件來修改
參考資料
- 【GitHub】RocksJava Basics
- 【man】nproc(1) — Linux manual page
- 【GitHub】Cannot execute YCSB #1105
- 【GitHub】[core] Fix ycsb.sh and ycsb.bat missing core dependencies #908
- 【CSDN】rocksdb 在 YCSB 中的運行教程
本文作者: ywang_wnlo
本文鏈接: https://ywang-wnlo.github.io/posts/4bc1e607.html
版權聲明: 本博客所有文章除特別聲明外,均采用 BY-NC-SA 許可協議。轉載請注明出處!