LevelDB是Google开源的持久化KV单机数据库,具有很高的随机写,顺序读/写性能,但是随机读的性能很一般,也就是说,LevelDB很适合应用在查询较少,而写很多的场景。
LevelDB的特点:
Fabric中使用了goleveldb包,即https://github.com/syndtr/goleveldb/。
goleveldb的基本操作:
Fabric中LevelDB代码,分布在common/ledger/util/leveldbhelper目录,目录结构如下:
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
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
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