初識:LevelDB
上篇文章緣起:BigTable可以說是已經把論文Bigtable: A Distributed Storage System for Structured Data
中的內容掰扯的明明白白,如果哪位小伙伴感覺還有不理解的點,可以點連接進去再反復琢磨幾遍,說不定就頓悟了呢~
之所以先花時間把BigTable掰扯了一篇,就是為了引出今天的主人公,LevelDB,接下來呢,我會一點點分享自己閱讀LevelDB源碼遇到的問題和學習到的一些技術,希望大家多多關注,如有問題,也請大家多多留言,一起學習,一起Happy~
LevelDB是個啥?
LevelDB是對BigTable中KV存儲分片Tablet的高度復刻,是由Jeff Dean和Sanjay Ghemawat,這兩位大牛也是BigTable論文的作者,盡管我們不能對BigTable的底層實現一探究竟,不過,開源的LevelDB還是可以讓我們對其管中窺豹呢~
簡而言之,LevelDB就是一個由Google開源的高效的單機Key/Value存儲系統,該存儲系統提供了Key到Value的有序映射。
LevelDB有啥特點
- LevelDB中Key/Value可以是任意長度的字節數組
- LevelDB中的數據是按Key有序存儲的,也就是說,范圍查詢效率會很高
- LevelDB支持用戶提供自定義Key排序規則
- 與其他KV存儲系統類似,提供
Put(key, value)
,Get(key)
,Delete(key)
這些基本操作 - LevelDB支持在一個原子批量操作中對同一個Key執行多次修改操作
- LevelDB通過瞬時快照(Transient Snapshot)為用戶提供一致的數據視圖
- LevelDB支持數據的前向/后向迭代遍歷
- LevelDB底層使用Snappy壓縮算法自動對數據進行壓縮
- LevelDB將外部活動(例如,文件系統操作)抽象為虛擬接口,為用戶自定義這些操作系統交互方式提供了便利,也就是說,用戶可以自定義底層到底是與Linux系統交互,還是與Windows系統交互,甚至於HDFS/GFS等分布式文件系統~
LevelDB有哪些限制
- LevelDB不是SQL數據庫,不存在關系數據模型,也不支持SQL查詢,同樣不支持索引
- 給定LevelDB數據庫,同一時刻,該數據庫只能由單進程(可能是多線程)訪問
- LevelDB庫本身不是基於C/S(Client/Server)模型的,也就是說,如果你想要像MySQL等各種其他數據庫那樣,通過客戶端連接遠程服務器的方式訪問LevelDB的話,那么,你需要自己將LevelDB包裝成服務端,然后再實現相應的客戶端才可以
這部分呢,先簡單介紹了LevelDB的特性以及使用限制,其實呢,也從側面給出了LevelDB的使用場景,比較適合單機KV存儲。
LevelDB快速上手
ε=(´ο`*)))唉、其實呢,我現在的主語言是Java,並不是C/C++,太久不用C/C++了,如果有啥錯誤,各位看官多多提點~
Windows下LevelDB從入門到放棄
Windows下編譯LevelDB太惡心了,TM有毒,放棄了、我只是想編譯調試下而已,各種攔路虎,算了,愛誰誰,真心感覺Windows下除了他自家的全家桶外,別的都不好用,就TM有毒,真是服氣了,不搞了,想在Windows下用LevelDB的,自己掂量着辦~
Linux下LevelDB快樂地玩耍
LevelDB編譯安裝
相比於Windows下LevelDB的編譯,Linux環境下簡直不要太友好,唯一的缺點就是,用Idea用習慣了,調試有點不太在行~
[root@cos leveldb-1.22]# mkdir -p build && cd build
# 注意:為了調試時可以進入LevelDB庫源碼,這里最好編譯成Debug版本
# 編譯成Debug版本
[root@cos build]# cmake -DCMAKE_BUILD_TYPE=Debug .. && cmake --build .
# 編譯成Release版本
[root@cos build]# cmake -DCMAKE_BUILD_TYPE=Release .. && cmake --build .
# 將鏈接文件拷貝到/usr/local/lib目錄下,以便程序調用
[root@cos build]# cp libleveldb.a /usr/local/lib/
# 將頭文件拷貝到/usr/local/include中,以便程序引用
[root@cos leveldb-1.22]# cp -r include/leveldb/ /usr/local/include/
LevelDB測試代碼
#include <cassert>
#include <iostream>
#include <string>
#include <leveldb/db.h>
int main() {
leveldb::DB* db;
leveldb::Options options;
// 配置項:如果LevelDB數據庫目錄不存在,則自動創建
options.create_if_missing = true;
leveldb::Status status = leveldb::DB::Open(options, "/root/testdb", &db);
assert(status.ok());
std::string key = "apple";
std::string value = "Apple";
// 將key/value鍵值對寫入LevelDB數據庫
leveldb::Status s = db->Put(leveldb::WriteOptions(), key, value);
std::string get;
// 寫入成功后,嘗試根據key進行檢索
if(s.ok()) {
s = db->Get(leveldb::ReadOptions(), key, &get);
}
if(s.ok()) {
std::cout << "讀取到Key=" << key << "對應的Value=" << get << "." << std::endl;
} else {
std::cout << "讀取失敗!" << std::endl;
}
delete db;
return 0;
}
編譯並執行程序,結果如下:
# 對main.cc源文件進行編譯
[root@cos leveldb]# g++ -o main main.cc -pthread -lleveldb -std=c++11
# 執行main可執行程序
[root@cos leveldb]# ./main
讀取到Key=apple對應的Value=Apple.
Linux下C/C++代碼調試
額(⊙o⊙)…前面說了,我不是做C/C++開發的,Linux是最小化安裝的,想調試下代碼,難為死我了,高手直接跳過就好~
GDB基本介紹
諸如GDB等代碼調試器的無外乎兩種功能:
- 幫助程序員看到程序執行時內部到底是個啥樣
- 幫助程序員知道其程序崩潰時程序正在干啥
基本上每種語言都有代碼調試器,而調試器的功能也無非就上面說的這兩種功能。
GDB能做的事情,大概可以分為四類,這四類功能可以幫助程序員快速定位Bug。
- 啟動應用程序,同時指定可能影響程序的參數
- 在指定條件下停止程序(斷點)
- 檢查程序停止時到底發生了計算(獲取程序執行到斷點時的狀態信息)
- 修改程序中的內容,使得程序員可以嘗試糾正Bug的影響,從而繼續調試代碼
通過Shell命令gdb
可以啟動GDB,一旦GDB啟動成功,程序員就可以不斷地在終端中輸入命令來告知GDB下一步要干嘛,如果想要終止的話,則需要輸入quit
命令。
用戶可以執行gdb
命令的同時不輸入任何參數,但是,大多數場景下,用戶會輸入1到2個參數,如下所示。
# 將可執行程序作為參數,程序編譯時需要添加-g參數
gdb program
# 將可執行程序以及core文件作為參數
gdb program core
# 如果想要調試正在運行的進程,則需要將進程ID作為第二個參數
gdb program 1234
gdb -p 1234
GDB常用命令
這里只是介紹一些常用的GDB命令,更多的話,大家去看man gdb
文檔吧
break [file:]functiop
:在指定文件[file]
的functiop
方法入口設置斷點
run [arglist]
:啟動程序,參數列表為arglist
bt
:Backtrace: 顯示程序棧
print expr
:計算表達式expr
的結果
c
:繼續執行程序,直到遇到下一個斷點
next
:執行下一行(除非遇到斷點);也就是說,該命令無論下一行調用多少方法,會直接跳過,除非函數內部有斷點
edit [file:]function
:查看指定文件中的方法的斷點信息
list [file:]function
:列出當前斷點附近的代碼
step
:執行下一行代碼,如果該行代碼有方法調用則進入該方法
help name
:展示GDB的name命令的幫助信息。
注意:上面命令中,next
縮寫為n
,step
縮寫為s
,分別是按行調試和單步調試,還有c
命令,都是非常常用的~
LevelDB代碼調試樣例
# 對main.cc源文件進行編譯,同時加入調試信息,后續可以使用gdb進行調試
[root@cos leveldb]# g++ -o main main.cc -pthread -lleveldb -std=c++11
# 使用gdb對main進行調試
[root@cos leveldb]# gdb -tui main
注意:為了調試方便,最好使用-tui
參數,這樣的話,調試時,就可以像Idea那樣,邊看代碼邊加斷點了~
調試時,大概就是下圖的樣子~
注意:如果在編譯LevelDB時未指定為Debug版本,則無法像圖2那樣進入到LevelDB源碼。
初識:LevelDB小結
其實吧,LevelDB的核心源碼及架構,我已經看的七七八八了,就是,本身我主語言是Java的,然后,我就一直沒有勇氣去Debug到源碼中仔細瞅一瞅,趁着這次梳理的機會,打算一點點跟進去看看、可能會更新的有點慢,不過,好事多磨,希望大家多多關注,同時也歡迎各位C/C++大佬多多指正,多多交流。
另外,大家可以關注我的微信公眾號,博客會同步更新的喲~
白嫖多不好,關注下再走唄~