LevelDB 簡介
壹、LevelDB入門
LevelDB是Google開源的持久化KV單機數據庫,具有
很高的隨機寫,順序讀/寫性能,但是隨機讀的性能很壹般,也就是說,LevelDB很適合應用在查詢較少,而寫很多的場景。LevelDB應用了LSM
(Log Structured Merge)
策略,lsm_tree對索引變更進行延遲及批量處理,並通過壹種類似於歸並排序的方式高效地將更新遷移到磁盤,降低索引插入開銷,關於LSM,本文在後
面也會簡單提及。
根據LevelDB官方網站的描述,LevelDB的特點和限制如下:
特點:
1、key和value都是任意長度的字節數組;
2、entry(即壹條K-V記錄)默認是按照key的字典順序存儲的,當然開發者也可以重載這個排序函數;
3、提供的基本操作接口:Put()、Delete()、Get()、Batch();
4、支持批量操作以原子操作進行;
5、可以創建數據全景的snapshot(快照),並允許在快照中查找數據;
6、可以通過前向(或後向)叠代器遍歷數據(叠代器會隱含的創建壹個snapshot);
7、自動使用Snappy壓縮數據;
8、可移植性;
限制:
1、非關系型數據模型(NoSQL),不支持sql語句,也不支持索引;
2、壹次只允許壹個進程訪問壹個特定的數據庫;
3、沒有內置的C/S架構,但開發者可以使用LevelDB庫自己封裝壹個server;
LevelDB本身只是壹個lib庫,在源碼目錄make編譯即可,然後在我們的應用程序裏面可以直接include leveldb/include/db.h頭文件,該頭文件有幾個基本的數據庫操作接口,下面是壹個測試例子:
#include <iostream>
#include <string>
#include <assert.h>
#include "leveldb/db.h"
using namespace std;
int main(void)
{ ?
leveldb::DB ?*db;
leveldb::Options ?options;
options.create_if_missing = true;
// open
leveldb::Status status = leveldb::DB::Open(options,"/tmp/testdb", &db);
assert(status.ok());
string key = "name";
string value = "chenqi";
// write
status = db->Put(leveldb::WriteOptions(), key, value);
assert(status.ok());
// read
status = db->Get(leveldb::ReadOptions(), key, &value);
assert(status.ok());
cout<<value<<endl;
// delete
status = db->Delete(leveldb::WriteOptions(), key);
assert(status.ok());
status = db->Get(leveldb::ReadOptions(),key, &value);
if(!status.ok()) {
cerr<<key<<" "<<status.ToString()<<endl;
} else {
cout<<key<<"==="<<value<<endl;
} ?
// close
delete db;
return 0;
}
上面的例子演示了如何插入、獲取、刪除壹條記錄,編譯代碼:
g++ -o test test.cpp libleveldb.a -lpthread -Iinclude
執行./test後,會在/tmp下面生成壹個目錄testdb,裏面包含若幹文件:
------------------------------------------------------------
LevelDB
是google開源的壹個key-value存儲引擎庫,類似於開源的Lucene索引庫壹樣。其他的軟件開發者可以利用該庫做二次開發,來滿足定制需
求。LevelDB采用日誌式的寫方式來提高寫性能,但是犧牲了部分讀性能。為了彌補犧牲了的讀性能,壹些人提議使用SSD作為存儲介質。
對於本地化的Key-value存儲引擎來說,簡單的使用壹般都分成三個基本的步驟:(1)打開壹個數據庫實例;(2)對這個數據庫實例進行插入,修改和查詢操作;(3)最後在使用完成之後,關閉該數據庫。下面將詳細討論該三個步驟:
壹、打開壹個數據庫實例
壹個leveldb數據庫有壹個對應壹個文件系統目錄的名字。該數據庫的所有內容都存儲在這個目錄下。下面的代碼描述了怎樣打開壹個數據庫或者建立壹個新的數據庫。
#include <assert.h>
#include "leveldb/db.h"
leveldb::DB* db;
leveldb::Options options;
options.create_if_missing = true;
leveldb::Status status = leveldb::DB::Open(options,"/tmp/testdb", &db);
assert(status.ok()); ?
如果打開已存在數據庫的時候,需要拋出錯誤。將以下代碼插在leveldb::DB::Open方法前面:
options.error_if_exists = true;
二、對數據庫的簡單讀、寫操作
LevelDB提供了Put,Delete和Get三個方法對數據庫進行修改和查詢。例如,下面的代碼片段描述了怎樣將key1對應的value值,移到key2對應的值。
std::string value;
leveldb::Status s = db->Get(leveldb::ReadOptions(), key1, &value);
if(s.ok()) s = db->Put(leveldb::WriteOptions(), key2, value);
if(s.ok()) s = db->Delete(leveldb::WriteOptions(), key1);
三、關閉數據庫
在對數據庫進行了壹系列的操作之後,需要對數據庫進行關閉。該操作比較簡單:
... open the db as described above...
... do something with db ...
delete db;
上面對levelDB的簡單使用做了基本的介紹,接下來就是如何自己寫壹個完成並且能運行的例子。
1、下載源碼 ?git clone /p/leveldb/
2、編譯源碼 ?cd leveldb && make all
3、編寫test.cpp
#include <assert.h>
#include <string.h>
#include <leveldb/db.h>
#include <iostream>
int main(){
leveldb::DB* db;
leveldb::Options options;
options.create_if_missing = true;
leveldb::Status status = leveldb::DB::Open(options,"/tmp/testdb", &db);
assert(status.ok());
//write key1,value1
std::string key="key";
std::string value = "value";
status = db->Put(leveldb::WriteOptions(), key,value);
assert(status.ok());
status = db->Get(leveldb::ReadOptions(), key, &value);
assert(status.ok());
std::cout<<value<<std::endl;
std::string key2 = "key2";
//move the value under key to key2
status = db->Put(leveldb::WriteOptions(),key2,value);
assert(status.ok());
status = db->Delete(leveldb::WriteOptions(), key);
assert(status.ok());
status = db->Get(leveldb::ReadOptions(),key2, &value);
assert(status.ok());
std::cout<<key2<<"==="<<value<<std::endl;
status = db->Get(leveldb::ReadOptions(),key, &value);
if(!status.ok()) std::cerr<<key<<" "<<status.ToString()<<std::endl;
else std::cout<<key<<"==="<<value<<std::endl;
delete db;
return 0;
}
4、編譯鏈接 g++ -o test test.cpp ../leveldb/libleveldb.a -lpthread -I../leveldb/include
註意libleveldb.a 和leveldb include的路徑。
5、運行結果./test:
value
key2===value
key NotFound: