1. 程式人生 > >區塊鏈教程Fabric1.0源代碼分析LevelDB KV數據庫

區塊鏈教程Fabric1.0源代碼分析LevelDB KV數據庫

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數據庫