区块链教程Fabric1.0源代码分析LevelDB KV数据库
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=%sn",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 感谢关注兄弟连区块链教程分享!
低调大师中文资讯倾力打造互联网数据资讯、行业资源、电子商务、移动互联网、网络营销平台。
持续更新报道IT业界、互联网、市场资讯、驱动更新,是最及时权威的产业资讯及硬件资讯报道平台。
转载内容版权归作者及来源网站所有,本站原创内容转载请注明来源。
- 上一篇
区块链教程Fabric1.0源代码分析Ledger statedb(状态数据库)-兄弟连区块链
Fabric 1.0源代码笔记 之 Ledger #statedb(状态数据库) 1、statedb概述 statedb,或VersionedDB,即状态数据库,存储了交易(transaction)日志中所有键的最新值,也称世界状态(world state)。可选择基于leveldb或cauchdb实现。 statedb,代码分布在core/ledger/kvledger/txmgmt/statedb目录下,目录结构如下: statedb.go,定义了核心接口VersionedDBProvider、VersionedDB、ResultsIterator和QueryResult,以及UpdateBatch和nsIterator结构体及方法。 util.go,包括工具函数EncodeValue和DecodeValue的实现。 stateleveldb目录,VersionedDBProvider和VersionedDB接口的leveldb版本实现,即stateleveldb.VersionedDBProvider和stateleveldb.versionedDB结构体及方法。 stateco...
- 下一篇
【剖析 | SOFARPC 框架】之SOFARPC 连接管理与心跳剖析
前言 在 RPC 调用过程中,我们经常会和多个服务端进行远程调用,如果在每次调用的时候,都进行 TCP连接,会对 RPC的性能有比较大的影响,因此,实际的场景中,我们经常要对连接进行管理和保持。 SOFARPC应用心跳包以及断线重连实现,结合系统tcp-keepalive机制,来实现对RPC连接的管理和保持。 连接管理 首先我们将会介绍连接管理相关的一些背景知识。 长连接和短连接 短连接,一般是指客户端向服务端发起连接请求。连接建立后,发送数据,接收服务端数据返回,然后触发连接断开,下次再重新重复以上过程。 长连接,则是在建立连接后,发送数据,接收数据,但是不主动断开,并且主动通过心跳等机制来维持这个连接可用,当再次有数据发送请求时,不需要进行建立连接的过程。 一般的,长连接多用于数据发送频繁,点对点的通讯,因为每个TCP连接都需要进行握手,这是
相关文章
文章评论
共有0条评论来说两句吧...
文章二维码
点击排行
推荐阅读
最新文章
- CentOS7设置SWAP分区,小内存服务器的救世主
- CentOS7安装Docker,走上虚拟化容器引擎之路
- SpringBoot2编写第一个Controller,响应你的http请求并返回结果
- CentOS8安装Docker,最新的服务器搭配容器使用
- SpringBoot2整合Redis,开启缓存,提高访问速度
- SpringBoot2配置默认Tomcat设置,开启更多高级功能
- Docker安装Oracle12C,快速搭建Oracle学习环境
- Docker使用Oracle官方镜像安装(12C,18C,19C)
- Springboot2将连接池hikari替换为druid,体验最强大的数据库连接池
- CentOS8,CentOS7,CentOS6编译安装Redis5.0.7