區塊鏈教程Fabric1.0源代碼分析LevelDB KV數據庫
阿新 • • 發佈:2018-11-01
try get 批量寫入 ror next() map 接口 fabric 基本 Fabric 1.0源代碼筆記 之 LevelDB(KV數據庫)
1、LevelDB概述
LevelDB是Google開源的持久化KV單機數據庫,具有很高的隨機寫,順序讀/寫性能,但是隨機讀的性能很一般,也就是說,LevelDB很適合應用在查詢較少,而寫很多的場景。
LevelDB的特點:
- key和value都是任意長度的字節數組;
- entry(即一條K-V記錄)默認是按照key的字典順序存儲的,當然開發者也可以重載這個排序函數;
- 提供的基本操作接口:Put()、Delete()、Get()、Batch();
- 支持批量操作以原子操作進行;
- 可以創建數據全景的snapshot(快照),並允許在快照中查找數據;
- 可以通過前向(或後向)叠代器遍歷數據(叠代器會隱含的創建一個snapshot);
- 自動使用Snappy壓縮數據;
- 可移植性;
Fabric中使用了goleveldb包,即https://github.com/syndtr/goleveldb/。
goleveldb的基本操作:
- 打開數據庫,db, err:=leveldb.OpenFile("./db", nil)。作用就是在當前目錄下創建一個db文件夾作為數據庫的目錄。
- 存儲鍵值,db.Put([]byte("key1"),[]byte("value1"),nil)。作用就是在數據庫中存儲鍵值對 key1-value1。leveldb數據庫中對鍵值的操作都是byte格式化的數據。
- 獲取鍵值對,data,_ := db.Get([]byte("key1"),nil),獲取key1對應的值。
- 遍歷數據庫,iter := db.NewIterator(nil, nil),for iter.Next(){ fmt.Printf("key=%s,value=%s\n",iter.Key(),iter.Value()) },iter.Release()。作用就是建立叠代器iter,然後依次遍歷數據庫中所有的數據並打印鍵和值,最後釋放叠代器iter。
- 關閉數據庫,db.Close()。
Fabric中LevelDB代碼,分布在common/ledger/util/leveldbhelper目錄,目錄結構如下:
- leveldb_provider.go,定義了結構體Provider、Provider、UpdateBatch、Iterator及其方法。
- leveldb_helper.go,定義了DB結構體及方法。
2、DB結構體及方法
DB結構體定義:對實際數據存儲的包裝。
type Conf struct {
????DBPath string //路徑
}
type DB struct {
????conf *Conf //配置
????db *leveldb.DB //leveldb.DB對象
????dbState dbState //type dbState int32
????mux sync.Mutex //鎖
????readOpts *opt.ReadOptions
????writeOptsNoSync *opt.WriteOptions
????writeOptsSync *opt.WriteOptions
}
//代碼在common/ledger/util/leveldbhelper/leveldb_helper.go
涉及如下方法:對goleveldb包做了封裝。
func CreateDB(conf *Conf) *DB //創建DB實例
func (dbInst *DB) Open() //leveldb.OpenFile,創建並打開leveldb數據庫(如目錄不存在則創建)
func (dbInst *DB) Close() //db.Close()
func (dbInst *DB) Get(key []byte) ([]byte, error) //db.Get
func (dbInst *DB) Put(key []byte, value []byte, sync bool) error //db.Put
func (dbInst *DB) Delete(key []byte, sync bool) error //db.Delete
func (dbInst *DB) GetIterator(startKey []byte, endKey []byte) iterator.Iterator //db.NewIterator,創建叠代器
func (dbInst *DB) WriteBatch(batch *leveldb.Batch, sync bool) error //db.Write,批量寫入
//代碼在common/ledger/util/leveldbhelper/leveldb_helper.go
3、DBHandle結構體及方法
DBHandle結構體定義:封裝DB,目的為給key添加dbName前綴,添加和拆除前綴通過constructLevelKey(h.dbName, key)和retrieveAppKey()實現。
type DBHandle struct {
????dbName string //DB名稱
????db *DB //type DB struct
}
//代碼在common/ledger/util/leveldbhelper/leveldb_provider.go
涉及如下方法:
func (h *DBHandle) Get(key []byte) ([]byte, error) //h.db.Get
func (h *DBHandle) Put(key []byte, value []byte, sync bool) error //h.db.Put
func (h *DBHandle) Delete(key []byte, sync bool) error //h.db.Delete
func (h *DBHandle) WriteBatch(batch *UpdateBatch, sync bool) error //h.db.WriteBatch
func (h *DBHandle) GetIterator(startKey []byte, endKey []byte) *Iterator //h.db.GetIterator
//代碼在common/ledger/util/leveldbhelper/leveldb_provider.go
補充UpdateBatch結構體及方法:
type UpdateBatch struct {
????KVs map[string][]byte
}
func NewUpdateBatch() *UpdateBatch //構造UpdateBatch
func (batch *UpdateBatch) Put(key []byte, value []byte) //batch.KVs[string(key)] = value
func (batch *UpdateBatch) Delete(key []byte) //batch.KVs[string(key)] = nil
//代碼在common/ledger/util/leveldbhelper/leveldb_provider.go
補充Iterator結構體及方法:封裝github.com/syndtr/goleveldb/leveldb/iterator
type Iterator struct {
????iterator.Iterator
}
func (itr *Iterator) Key() []byte //itr.Iterator.Key()拆除dbName
func constructLevelKey(dbName string, key []byte) []byte //為key添加dbName
func retrieveAppKey(levelKey []byte) []byte //為key拆除dbName
//代碼在common/ledger/util/leveldbhelper/leveldb_provider.go
4、Provider結構體及方法
Provider結構體定義:將單個物理LevelDB,虛擬為多個邏輯LevelDB
type Provider struct {
????db *DB
????dbHandles map[string]*DBHandle
????mux sync.Mutex
}
//代碼在common/ledger/util/leveldbhelper/leveldb_provider.go
涉及方法如下:
func NewProvider(conf *Conf) *Provider {//創建並打開db,構造Provider
????db := CreateDB(conf)
????db.Open()
????return &Provider{db, make(map[string]*DBHandle), sync.Mutex{}}
}
//獲取名稱為dbName的leveldb句柄
func (p *Provider) GetDBHandle(dbName string) *DBHandle {
????p.mux.Lock()
????defer p.mux.Unlock()
????dbHandle := p.dbHandles[dbName]
????if dbHandle == nil {
????????dbHandle = &DBHandle{dbName, p.db}
????????p.dbHandles[dbName] = dbHandle
????}
????return dbHandle
}
//關閉leveldb
func (p *Provider) Close() {
????p.db.Close()
}
//代碼在common/ledger/util/leveldbhelper/leveldb_provider.go
感謝關註兄弟連區塊鏈教程分享!
區塊鏈教程Fabric1.0源代碼分析LevelDB KV數據庫