項目上有一個性能優化的需求,需要進一步優化遠程調用Redis導致的RT偏高問題,目前的想法是做兩級緩存,通過加入一個基於嵌入式數據庫引擎的本地緩存,來降低對遠端redis的依賴;大致的結構如下:
業務服務 —> 本地數據庫引擎 -> 遠端redis
之所以用數據庫引擎,是因爲在滿足QPS的情況下,想儘可能本地化更多的數據,直接用內存太奢侈了。
對於讀操作:優先讀取本地,本地沒有的話,再讀區遠端redis,遠端的值會寫回到本地
對於寫操作:直接寫本地,然後後臺線程異步同步至遠端,其中業務邏輯可以容忍短時的數據不一致情況。
WiredTiger是mongodb收購過來的一個存儲引擎,從2.3版本之後,便是mongodb的默認引擎。
除了WiredTiger之外,一些本地的嵌入式數據庫引擎還有:地址
相比Google的LevelDb引擎的性能對比:鏈接
本文主要記錄WiredTiger安裝的流程,以及一個簡單的Java操作示例,安裝的環境:
$system_profiler SPSoftwareDataType
Software:
System Software Overview:
System Version: macOS 10.14.6 (18G48f)
Kernel Version: Darwin 18.7.0
Boot Volume: Untitled
Boot Mode: Normal
Computer Name: yuanke’s MacBook Ali
User Name: yuanke wei (yuankewei)
Secure Virtual Memory: Enabled
System Integrity Protection: Enabled
Time since boot: 17 days 5:20
(1)git下載相關的代碼,並切換到穩定分支
$git clone git://github.com/wiredtiger/wiredtiger.git
$cd wiredtiger/
$git checkout -b mongodb-4.4 origin/mongodb-4.4
(2)安裝相關編譯工具
#採用brew安裝
$brew install autoconf automake libtool swig
(3)開始編譯
$./autogen.sh
#mac下查看JAVA_HOME的命令爲:
$/usr/libexec/java_home
#**編輯生成的configure文件,
17620行開始,替換
case "$host_os" in
darwin*) _JTOPDIR=`echo "$_JTOPDIR" | sed -e 's:/[^/]*$::'`
_JINC="$_JTOPDIR/Headers";;
*) _JINC="$_JTOPDIR/include";;
esac
爲
case "$host_os" in
*) _JINC="$_JTOPDIR/include";;
esac
$./configure --enable-java --enable-python
#開始編譯
$make
#安裝相關庫文件到/usr/local/
$make install
(4)採用idea建立一個maven工程
#wiredtiger安裝之後,java的jar包和jni本地庫的位置爲:
$ls /usr/local/share/java/wiredtiger-3.2.0/
libwiredtiger_java.0.dylib libwiredtiger_java.dylib wiredtiger.jar
libwiredtiger_java.a libwiredtiger_java.la
編輯idea的工程,引入對應的jar包
Project Settings -> Libraries
另外,運行測試程序時,還需要加入jni本地庫的路徑,idea的jvm運行參數重加入:
-Djava.library.path=/usr/local/share/java/wiredtiger-3.2.0
完整的測試程序如下
import com.wiredtiger.db.*;
public class Main {
public static void main(String[] args) {
Connection conn;
Session s;
Cursor c;
try {
//保證目錄是存在的/Users/yuankewei/temp/WT_HOME
conn = wiredtiger.open("/Users/yuankewei/temp/WT_HOME", "create");
s = conn.open_session(null);
} catch (WiredTigerException wte) {
System.err.println("WiredTigerException: " + wte);
return;
}
/*! [access example connection] */
try {
/*! [access example table create] */
//創建了一個table,key是一個String,Value也是一個String
s.create("table:t", "key_format=S,value_format=S");
/*! [access example table create] */
/*! [access example cursor open] */
c = s.open_cursor("table:t", null, null);
/*! [access example cursor open] */
} catch (WiredTigerException wte) {
System.err.println("WiredTigerException: " + wte);
return;
}
/*! [access example cursor insert] */
//插入一個數據
try {
c.putKeyString("foo");
c.putValueString("bar");
c.insert();
} catch (WiredTigerPackingException wtpe) {
System.err.println("WiredTigerPackingException: " + wtpe);
} catch (WiredTigerException wte) {
System.err.println("WiredTigerException: " + wte);
}
/*! [access example cursor insert] */
//再插入一行數據
try {
c.putKeyString("foo1");
c.putValueByteArray("bar1".getBytes());
c.insert();
} catch (WiredTigerPackingException wtpe) {
System.err.println("WiredTigerPackingException: " + wtpe);
} catch (WiredTigerException wte) {
System.err.println("WiredTigerException: " + wte);
}
//根據key查詢value
try {
c.reset();
c.putKeyString("foo1");
c.search();
System.out.println(c.getValueString());
} catch (Exception e) {
}
/*! [access example cursor insert] */
/*! [access example cursor list] */
//遍歷數據
try {
c.reset();
while (c.next() == 0) {
System.out.println("Got: " + c.getKeyString() + ", " + new String(c.getValueByteArray()));
}
} catch (WiredTigerPackingException wtpe) {
System.err.println("WiredTigerPackingException: " + wtpe);
} catch (WiredTigerException wte) {
System.err.println("WiredTigerException: " + wte);
}
}
}
程序的數據爲:
bar1
Got: foo, bar
Got: foo1, bar1