NoSQL是如今互聯網Web2.0時代備受關注的技術之一,被用來存儲大量的非關係型的數據。Berkeley DB做爲一款優秀的Key/Value存儲引擎天然也在討論之列。最近使用BDB來發一個KV系統,並將這段時間的BDB的學習和使用經驗記錄以下。(項目中使用了BDB的4.8.30版本,本文全部涉及的具體問題都基於該版本)。html
1. Berkeley DB的簡介程序員
Berkeley DB(BDB)是一個高性能的嵌入式數據庫編程庫(引擎),它能夠用來保存任意類型的鍵/值對 (Key/Value Pair),並且能夠爲一個鍵保存多個數據。Berkeley DB能夠支持數千的併發線程同時操做數據庫,支持最大256TB的數據。算法
BDB提供諸如C語言,C++,Java,Perl,Python,Tcl等多種編程語言的API,而且普遍支持大多數類Unix操做系統和Windows操做系統以及實時操做系統(如 VxWorks)。數據庫
1991年,Berkeley DB的第一個版發行(Linux系統也在這一年誕生),其最初的開發目的是以新的HASH訪問算法來代替舊的hsearch函數和大量的dbm實現,該版本還包含了B+樹數據訪問算法。編程
1992年,BSD UNIX第4.4發行版中包含了Berkeley DB1.85版。基本上認爲這是Berkeley DB的第一個正式版。windows
1996年,Sleepycat軟件公司成立,提供對Berkeley DB的商業支持。緩存
2006年,Sleepycat被Oracle收購,當時最新版本是4.7.25。併發
2. 直觀瞭解Berkeley DB軟件包oracle
Berkeley DB是一款開源軟件,咱們能夠從Oracle的官方網站獲得其源代碼包。其源代碼目錄是由一系列子目錄組成,從BDB的實現角度按照功能層次可將它們簡單歸類,劃分以下:框架
a. DB核心模塊(db);
b. 各子系統模塊(存儲管理子系統:btree/hash/qam;內存池管理子系統:mp;事務子系統:txn;鎖子系統:mutex;日誌子系統:log);
c. 操做系統抽象層(os_brew/os_s60/os_windows等);
d. Build目錄(build_brew/build_s60/build_windows等);
e. 工具程序(db_archive/db_checkpoint等);
f. 語言API支持;
g. 例子(examples_c/examples_csharp等);
h. 其它;
經過源代碼編譯安裝BDB很簡單,代碼以下:
cd ./db-4.8.30/build_unix
../disk/configure --prefix=<dir>
make && make install
安裝目標目錄(/usr/local/BerkeleyDB.4.8)包含四個子目錄:
A. bin 一些實用工具
B. docs 文檔
C. include 包含了使用BDB庫開發程序時的頭文件
D. lib 包含了使用BDB庫開發程序時須要鏈接的庫文件
3. 如何得到BDB的相關知識
BDB提供裏很是詳細的文檔,能夠官方網站得到html或pdf版本的文檔。這裏對pdf版本的一些文檔簡介以下:
BDB_Installation.pdf: BDB的安裝文檔,涵蓋了不一樣操做系統,不一樣的編譯工具,不一樣編程語言等多方面的詳細信息;
BDB_Prog_Reference.pdf: 該文檔是使用BDB的開發人員的參考手冊,主要從BDB的各類功能和機制的原理進行闡述,供使用BDB做爲存儲引擎來編寫程序的各種程序員(C、Java、C#、Perl)閱讀;
BDB-Porting-Guide.pdf: 該文檔是給須要將BDB移植到一個新的平臺開發人員準備的;
InMemoryDBApplication.pdf: 基於內存的BDB應用的相關知識;
BDB-C_APIReference.pdf: C API參考手冊,跟BDB_Prog_Reference.pdf結合使用;
BerkeleyDB-Core-C-GSG.pdf: 爲C語言開發人員提供的BDB的入門手冊;
BerkeleyDB-Core-C-Txn.pdf: 爲C語言開發人員提供的BDB事務方面的手冊;
Replication-C-GSG.pdf: 爲C語言開發人員提供的BDB複製方面的手冊;
4. 以上對源碼目錄的分類是從實現角度按照層次進行劃分的,若是從BDB的功能模塊,或者說是從系統結構角度進行劃分,可將其分爲幾個子系統:
存儲管理子系統 (Storage Subsystem)
內存池管理子系統 (Memory Pool Subsystem)
事務子系統 (Transaction Subsystem)
鎖子系統 (Locking Subsystem)
日誌子系統 (Logging Subsystem)
5. 以上的五個子系統完成了BDB做爲一個Database所須要的大部分功能,如何駕馭以上子系統來完成咱們須要的任務是關鍵。像MySQL這種獨立的RDBMS,咱們能夠經過配置和SQL語句來控制和使用它的各類功能。因爲BDB是一個嵌入式的數據庫,最終仍是須要程序員經過調用API來完成。因此要使用好BDB,須要先了解其原理,而後在合適的位置上調用合適的API。
寫一個BDB程序的通常步驟:
a. 建立、設置和打開Environment;b. 建立、設置和打開Database;c. 訪問Database;d. 關閉Database;e. 關閉Environment。
此處的Database是從屬於Environment,即db是在env這個環境上面創建起來的。爲了便於快速把握重點,能夠用BDB跟通常的RDBMS作個類比,這裏的Database至關於數據表,Environment至關於數據庫。
DB_ENV *dbenv;
DB *dbp;
int ret;
if ((ret = db_env_create(&dbenv, 0)) != 0) {
fprintf(errfp, "%s: %s\n", progname, db_strerror(ret));
return (1);
}
dbenv->set_errfile(dbenv, errfp);
dbenv->set_errpfx(dbenv, progname);
if ((ret = dbenv->set_cachesize(dbenv, 0, 64 * 1024, 0)) != 0) {
dbenv->err(dbenv, ret, "set_cachesize");
dbenv->close(dbenv, 0);
return (1);
}
(void)dbenv->set_data_dir(dbenv, data_dir);
if ((ret = dbenv->open(dbenv, home, DB_CREATE | DB_INIT_LOCK | DB_INIT_LOG | DB_INIT_MPOOL | DB_INIT_TXN, 0644)) != 0) {
dbenv->err(dbenv, ret, "environment open: %s", home);
dbenv->close(dbenv, 0);
return (1);
}
if ((ret = db_create(&dbp, dbenv, 0)) != 0){
fprintf(errfp, "%s: %s\n", progname, db_strerror(ret));
return (1);
}
if ((ret = dbp->open(dbp, NULL, "exenv_db1.db", NULL, DB_BTREE, DB_CREATE,0644)) != 0){
fprintf(stderr, "database open: %s\n", db_strerror(ret));
return (1);
}
if ((ret = dbp->close(dbp, 0)) != 0) {
fprintf(stderr, "database close: %s\n", db_strerror(ret));
return (1);
}
if ((ret = dbenv->close(dbenv, 0)) != 0) {
fprintf(stderr, "DB_ENV->close: %s\n", db_strerror(ret));
return (1);
}
return (0);
數據文件:
一個BDB的實例會產生數據存儲文件,數據文件的目錄由dbenv->set_data_dir(dbenv, data_dir);這條語句來指定。涉及的文件類型有:Data Files,Log Files,Region Files, Temporary Files。
Data Files:數據文件,存儲實際的數據;
Log Files:日誌文件;
Region Files:是各個子系統保存信息的文件,若是在Env中設置了DB_PRIVATE選項,這些信息是被一個進程私有,即它們保存在內存中,這些文件在此種狀況下不產生;
Temporary Files: 臨時文件,特使狀況會被建立;
數據的存數格式:
Berkeley DB提供瞭如下四種文件存儲方法:哈希文件、B樹、定長記錄(隊列)和變長記錄(基於記錄號的簡單存儲方式),應用程序能夠從中選擇最適合的文件組織結構。以上代碼經過db->open函數中設置了DB_BTREE這個選項指定其使用B樹方式存儲。其它的三種存儲格式對應的類型爲:DB_HASH,DB_QUEUE,DB_RECNO。
事務提交:
BDB中的事務提交有兩種方式:DB_AUTO_COMMIT和顯式提交事務。若是設置爲DB_AUTO_COMMIT,則每步操做多做爲單獨的事務自動提交;若是須要顯示提交,則須要顯示調用具體事務相關的begin/end API(相見文檔BerkeleyDB-Core-C-Txn.pdf)。
BDB在事務提交時也是遵循先寫日誌並刷新到磁盤的方式,可是爲了提升性能,其又引入了兩個選項:DB_TXN_NOSYNC和DB_TXN_WRITE_NOSYNC。DB_TXN_NOSYNC的做用是使BDB在事務提交的時候不嚴格要求日誌到磁盤,刷新與否取決於日誌緩衝;DB_TXN_WRITE_NOSYNC會比DB_TXN_NOSYNC稍顯嚴格,其含義是要求事務提交刷新日誌,但只是刷到操做系統文件緩存當中。
BDB的事務隔離性級別有三個:READ UNCOMMITED、READ COMMITED、SERIALIZABLE
CheckPoint:
執行一個檢查點會完成的工做有:Flushes all dirty pages from the in-memory cache to database files;Writes a checkpoint record;Flushes the log to log files;Writes a list of open databases.
調用API DB_ENV->txn_checkpoint(); 便可完成,若是是非DB_PRIVATE的Env,也可使用BDB自帶的工具db_checkpoint。爲了不出現一個檢查點提交大量數據的狀況,BDB還提供了輕量級刷新髒頁的API:DB_ENV->memp_trickle();
Replication:
BDB中提供了兩種方式來支持複製技術:Replication Base API和Replication Manager。能夠說Replication Base API是最基礎的API,實現方式靈活,功能強大,可是編碼量大;Replication Manager至關於框架,使用方式簡單,編碼量小。Replication Manager可能可以知足大部分用戶的需求,但不是全部需求,因此靈活性不足。若是您的須要是Replication Manager不能知足的,請使用Replication Base API本身實現複製策略。Replication Manager的主從策略有兩種:指定主從、自動推舉主從。
分區:
BDB的分區機制是從db-4.8.x以後剛引入的新功能,涉及到的API有兩個:
DB->set_partition() 設置分區方式,包含了一個分區方式的回調函數,用戶能夠經過編寫代碼來本身實現分區方式,很是靈活。(詳見API手冊BDB-C_APIReference.pdf)
DB->set_partition_dirs() 設置分區目錄。(詳見API手冊BDB-C_APIReference.pdf)
備份:
BDB有三種備份方式:
Offline Backups:離線備份,停服務拷貝數據目錄;
Hot Backups:使用API或者BDB自帶工具db_backup在DB在使用狀況作備份;
Incremental Backups:增量備份;
具體細節詳見BerkeleyDB-Core-C-Txn.pdf。
6. 如下是可能獲取到Berkeley DB資源的連接:
官方主頁:
http://www.oracle.com/database/berkeley-db/db/index.html
產品下載:
http://www.oracle.com/technology/software/products/berkeley-db/index.html
官方開發者文檔中心:
http://www.oracle.com/technology/documentation/berkeley-db/db/index.html