閱讀584 返回首頁    go 阿裏雲 go 技術社區[雲棲]


[leveldb] 初探 leveldb

[TOC]

1、 leveldb 簡介

leveldb 是 Google 用 C++ 開發的一個快速的 鍵值對存儲數據庫(持久化KV單機數據庫),提供從字符串鍵到字符串值的有序映射,具有很高的隨機寫,順序讀/寫性能,但是隨機讀的性能很一般,也就是說,LevelDB很適合應用在查詢較少,而寫很多的場景。

LevelDB應用了 LSM (Log Structured Merge) 策略,lsm_tree對索引變更進行延遲及批量處理,並通過一種類似於歸並排序的方式高效地將更新遷移到磁盤,降低索引插入開銷,關於LSM,本文在後麵也會簡單提及。

根據LevelDB官方網站的描述,LevelDB的特點和限製如下:

1-1 特點

  • 1、key和value都是任意長度的字節數組;
  • 2、entry(即一條K-V記錄)默認是按照key的字典順序存儲的,當然開發者也可以重載這個排序函數;
  • 3、提供的基本操作接口:Put()、Delete()、Get()、Batch();
  • 4、支持批量操作以原子操作進行;
  • 5、可以創建數據全景的snapshot(快照),並允許在快照中查找數據;
  • 6、可以通過前向(或後向)迭代器遍曆數據(迭代器會隱含的創建一個snapshot);
  • 7、自動使用Snappy壓縮數據;
  • 8、可移植性;

1-2 限製

  • 1、非關係型數據模型(NoSQL),不支持sql語句,也不支持索引;
  • 2、一次隻允許一個進程訪問一個特定的數據庫;
  • 3、沒有內置的C/S架構,但開發者可以使用LevelDB庫自己封裝一個server;

LevelDB本身隻是一個lib庫,在源碼目錄make編譯即可,然後在我們的應用程序裏麵可以直接include leveldb/include/db.h頭文件

2、 leveldb 安裝

2-1 下載 leveldb

wu_being@UbuntuKylin1704:~/Github/leveldb$ git clone https://github.com/google/leveldb

2-2 編譯 leveldb

wu_being@UbuntuKylin1704:~/Github/leveldb$ cd leveldb/
wu_being@UbuntuKylin1704:~/Github/leveldb$ make

編譯的動態庫和靜態庫分別在 out-shared,out-static 下:

wu_being@UbuntuKylin1704:~/Github/leveldb$ ls leveldb/out-shared/libleveldb.so.1.20
wu_being@UbuntuKylin1704:~/Github/leveldb$ ls leveldb/out-static/libleveldb.a

2-3 安裝 leveldb

隻有動態庫需要安裝如果靜態庫在編譯後直接鏈接即可。 (動態庫靜態庫請看文章後來更多鏈接)

# cp leveldb header file
wu_being@UbuntuKylin1704:~/Github/leveldb$ sudo cp -r /leveldb/include/ /usr/include/

# cp lib to /usr/lib/
wu_being@UbuntuKylin1704:~/Github/leveldb$ sudo cp /leveldb/out-shared/libleveldb.so.1.20 /usr/lib/

# create link
wu_being@UbuntuKylin1704:~/Github/leveldb$ sudo ln -s /usr/lib/libleveldb.so.1.20 /usr/lib/libleveldb.so.1
wu_being@UbuntuKylin1704:~/Github/leveldb$ sudo ln -s /usr/lib/libleveldb.so.1.20 /usr/lib/libleveldb.so

# update lib cache
wu_being@UbuntuKylin1704:~/Github/leveldb$ sudo ldconfig

查看動態庫安裝是否成功

wu_being@UbuntuKylin1704:~/Github/leveldb$ ls /usr/lib/libleveldb.so*
# 顯示下麵 3 個文件即安裝成功
/usr/lib/libleveldb.so.1.20
/usr/lib/libleveldb.so.1
/usr/lib/libleveldb.so

3、 leveldb 使用

我們的 leveldb目錄下編寫一個 test.cpp 來測試我們的 leveldb。將key1對應的value值,移到key2對應的值。。

#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;    
    // options.error_if_exists = true;

    // open
    leveldb::Status status = leveldb::DB::Open(options,"/tmp/testdb2", &db);    
    assert(status.ok());    

    string key1  = "name1";
    string key2  = "name2";    
    string value = "wuchengbing12";    

    // write key1
    status = db->Put(leveldb::WriteOptions(), key1, value);    
    assert(status.ok());    

    // read key1
    status = db->Get(leveldb::ReadOptions(), key1, &value);    
    assert(status.ok());    

    cout<<value<<endl;    

    // write key2
    status = db->Put(leveldb::WriteOptions(), key2, value);    
    assert(status.ok());    

    // delete key1
    status = db->Delete(leveldb::WriteOptions(), key1);    
    assert(status.ok());        

    status = db->Get(leveldb::ReadOptions(),key2, &value);    
    // assert(status.ok());        
    if(!status.ok()) {
        cerr<<key2<<"    "<<status.ToString()<<endl;
    } else {
        cout<<key2<<"==="<<value<<"==="<<status.ToString()<<endl;    
    }   

    // close 
    delete db;    

    return 0;    
} 

3-1 編譯 - 靜態鏈接

wu_being@UbuntuKylin1704:~/Github/leveldb$ cp out-static/libleveldb.a ./
wu_being@UbuntuKylin1704:~/Github/leveldb$ g++ test.cpp -o test ./libleveldb.a -lpthread -Iinclude

3-2 編譯 - 動態鏈接

wu_being@UbuntuKylin1704:~/Github/leveldb$ g++ test.cpp -o test -lpthread -lleveldb -Iinclude

3-3 運行結果

# 輸出值為 a,說明成功存儲和獲取
wu_being@UbuntuKylin1704:~/Github/leveldb$ ./test 
wuchengbing12
name2===wuchengbing12===OK
wu_being@UbuntuKylin1704:~/Github/leveldb$

# 查看數據庫
wu_being@UbuntuKylin1704:~/Github/leveldb$ ls /tmp/testdb2/ -l
總用量 24
-rw-r--r-- 1 wu_being wu_being 166 11月 13 13:14 000005.ldb
-rw-r--r-- 1 wu_being wu_being 106 11月 13 13:14 000006.log
-rw-r--r-- 1 wu_being wu_being  16 11月 13 13:14 CURRENT
-rw-r--r-- 1 wu_being wu_being   0 11月 13 13:14 LOCK
-rw-r--r-- 1 wu_being wu_being 310 11月 13 13:14 LOG
-rw-r--r-- 1 wu_being wu_being  57 11月 13 13:14 LOG.old
-rw-r--r-- 1 wu_being wu_being  83 11月 13 13:14 MANIFEST-000004
wu_being@UbuntuKylin1704:~/Github/leveldb$ 

4、 代碼解釋

4-1 打開一個數據庫實例

一個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;

4-2 對數據庫的簡單讀、寫操作

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);

4-3 關閉數據庫

在對數據庫進行了一係列的操作之後,需要對數據庫進行關閉。該操作比較簡單:

... open the db as described above...    
... do something with db ...    
delete db;

5、 更多鏈接

C語言的靜態庫與共享庫使用:https://blog.csdn.net/u014134180/article/details/78335274

Wu_Being博客聲明:本人博客歡迎轉載,請標明博客原文和原鏈接!謝謝!
《[leveldb] 初探 leveldb》: https://yq.aliyun.com/articles/241407/

Wu_Being 吳兵博客接受讚助費二維碼

如果你看完這篇博文,覺得對你有幫助,並且願意付讚助費,那麼我會更有動力寫下去。

最後更新:2017-11-13 14:04:20

  上一篇:go  PostgreSQL Oracle兼容性 之 - parser SQL保留|關鍵字(keywrods)大全
  下一篇:go  新科技新文娛:從天貓雙11看優酷背後的產品技術升級