超级帐本支持多帐本(详细内容参考第7章实现数据隔离的多链及多通道),每一个帐本的数据是分开存储的。数据库
帐本编号(LedgerID)的数据存储在LevelDB数据库中,只是记录了有哪些版本,建立新的帐本会检查是否有相同的帐本编号存在,数组
这保证了全局惟一性。帐本编号库并不存储与区块相关的数据。这和区块索引不同。数据结构
帐本数据(Ledger)是以二进制文件的形式存储的,每一个帐本数据存储在不一样的目录下。app
后面内容都是在已经区分了帐本的状况下再对数据进行查询的。区块链
基于文件系统的区块存储实现了以下功能接口。优化
【1】。帐本存储管理atom
A。提交区块到帐本(AddBlock)spa
B。获取区块链信息(GetBlockchainInfo)设计
C。获取区块数据(RetrieveBlocks)3d
D。关闭区块存储(Shutdown)
【2】。索引管理:跟踪区块和交易保存在哪一个文件。
A。根据哈希值获取区块(RetrieveBlockByHash)
B。根据区块编号获取区块(RetrieveBlockByNumber)
C。根据交易编号获取交易(RetrieveTxByID)
D。根据区块编号和交易编号获取交易(RetrieveTxByBlockNumTranNum)
E。根据交易编号获取区块(RetrieveBlockByTxID)
F。根据交易编号获取交易验证码(RetrieveTxValidationCodeByTxID)
帐本数据的全部操做都是经过区块文件管理器(blockfileMgr)实现的,定义以下:
type blockfileMgr struct{ rootDir String //区块链中区块存储的根目录 conf *Conf //配置信息 db *leveldbhelper.DBHandle //数据库指针 index index //区块索引接口 cpInfo *checkpointInfo //区块检查点信息 cpInfoCond *sync.Cond //条件变量 currentFileWriter *blockfileWriter //当前写入区块文件的指针 bcInfo atomic.Value //区块链信息 }
区块文件管理器实现的功能分为几类:
【1】帐本数据存储管理
A。肯定文件存储在哪一个目录
B。肯定区块存储在哪一个文件
【2】检查点管理:跟踪最新持久化存储的文件
【3】索引管理:跟踪区块和交易保存在哪一个文件
"data":"$rawJSON"
}
在超级帐本中:
【1】若是存储的类型是JSON,且JSONValue的data字段是状态值通过JSON序列化后的内容,则CouchDoc中的Attachments为空;
【2】若是存储的类型是字节数组,则JSONValue只保存版本信息,data字段为空,状态值放在Attachments的AttachmentBytes中,Attachments的Name为“valueBytes”,ContentType为“application/octet-stream”。在获取时根据data字段是否为空能够判断出存储的状态值类型,最后获得存储的版本和状态值。
条件查询是基于LevelDB的状态数据库所没有的功能进行的。查询前会对查询条件进行转换,增长“data.”前缀和查询记录限制等,查询结果还会默认增长“_id”"version""chaincodeid"。好比原始的查询条件为:
{
"selector":{
"owner":{
"$seq":"tom"
}
},
“fields”:[
"owner",
"asset_name",
"color",
"size"
],
"sort":[
"size",
"color"
]
}
转换后的查询条件为:
{
"selector":{
"$and":[
{
"chaincodeid":"marble"
},
{
历史信息记录最细的粒度就是交易,若在一个交易中屡次对同一个writeKey更新数据,则会以第一次数据为准,历史信息实际存储的信息是固定的空字节数组[]byte{}。
更新区块信息的时候,会同步更新检查点信息,保存的内容是最新的区块高度和最大的交易序号,检查点信息用来判断历史信息的状态是不是最新的。
区块的提交过程分为3个步骤:
【1】。先保存区块到文件存储的帐本数据中
【2】。而后更新状态数据
【3】。最后更新历史信息数据
这3个步骤是顺序执行的,在这个过程当中有文件的操做,也有数据库的操做,因此在任何一个步骤均可能出现错误或者中断。恢复的过程会根据帐本数据记录的区块信息和状态数据,历史信息数据的检查点进行比较,从新提交检查点以后的区块信息,保持帐本数据的一致性。
本章小结:
本章介绍了Hyperledger Fabric 1.0的数据存储,包括帐本数据(Ledger)、区块索引(Index)、状态数据(state Database)、历史数据(Hisotry database)等存储结构。目前的数据存储存在较大的优化空间,帐本数据结构的设计带来的开销很大,最新的版本并无实现帐本载剪(Ledger Prune)功能,不能进行归档,也不能删除无效交易,因此会致使存储空间持续增加。