Hyperledger Fabric数据存储结构

Hyperledger Fabric数据存储结构

概述

Hyperledger Fabric支持多链。每个链对应一套账本。所以区块链每个peer节点会维护多套账本。每个超级账本包含以下元素:

  • 账本编号:快速查询存在哪些账本
  • 账本数据:实际的区块数据存储
  • 区块索引:快速查询区块/交易
  • 状态数据:最新的世界状态数据
  • 历史数据:跟踪键的历史

每个peer节点会维护4个DB,它们分别是:

  • idStore,存储chainID。用户快速查询节点存在哪些账本
  • stateDB,存储world state(默认为LevelDB,可替换为CouchDB)
  • historyDB,存储stateDB的key的版本变化
  • blockIndex,存储区块文件索引

如下图:(因只展示了单链的数据存储情况,故idStore未在图中展示)


fabric db.png

其中,世界状态和账本数据是两个账本最重要的组成部分。


ledger.png

账本编号(LedgerId)

账本编号的数据存储在LevelDB数据库中,只是记录了有哪些账本,创建新的账本会检查是否有相同的账本编号存在,保证了全局唯一性。账本编号库并不存储与区块相关的数据。

账本数据(Ledger)

账本数据是以二进制文件的形式存储的,每个账本数据存储在不同的目录下。账本数据的所有操作都是通过区块文件管理器(blockfileMgr)实现的。区块文件管理器创建的文件以“blockfile_”为前缀,6位数字为后缀,后缀必须是从小到大连续的数字,中间不能有缺失。默认的区块文件大小上限是64M(目前这个大小是硬编码在代码中的),一个账本能保存最大数据量大概是61TB。
下图是区块账本数据的结构:


ledgerdata.png
  • 信息描述:B代表区块链账本数据。其中B0为创世区块,其中包含了区块头H0,区块数据D0(因为是创世区块,区块数据里不包含交易数据),区块元数据M0。区块B1区块头H1,其中包含了前一个区块B0的加密hash和本身区块的加密hash。

区块(Block)

block.png

每个区块包含三个部分。

区块头(Block Header)

区块数(Block Number):一个从0(创世区块)开始的整数,并且对于附加到区块链的每个新块增加1。
当前区块hash(Current Block Hash):当前区块中包含的所有交易的hash。
前一区块hash(Previous Block Hash):前一个区块的hash。

区块数据(Block Data)

区块数据包含了一组交易,交易在区块创建时写入。

区块元数据(Block Matadata)

元数据包含了区块创建时间,写入程序的证书,公钥和签名。

交易(transaction)

transaction.png

交易头(Header)

交易头中包含了一些重要的交易元数据,例如链码的名称、版本。

签名(Signature)

包含由application创建的加密签名。它是由application的私钥生成的。用于检查交易有没有被篡改。

交易提案(Proposal)

包含了由application生成的交易请求参数。

交易提案返回(Response)

包含了由背书节点返回的模拟执行结果(读写集RWset)。这是链码的输出,如果交易验证通过,这些数据会被用于更新世界状态。

背书(Endorsements)

包含了交易的背书。一个返回对应多个背书。

区块索引(Block Index)

Hyperledger Fabric提供了多种区块索引的方式,以便能快速找到区块。索引的内容是文件位置指针(File Location Pointer)。文件位置指针由三个部分组成:所在文件的编号(fileSuffixNum)、文件内的偏移量(offset)、区块占用的字节数(bytesLength)。

状态数据(State Database)

状态数据(state database)记录的是交易执行的结果,最新的状态代表了通道(channel)上所有键的最新值,所以又称为“世界状态”。状态数据库目前支持LevelDB和CouchDB。

  • LevelDB(默认的KV数据库):支持键的查询,组合键的查询、范围键的查询。
  • CouchDB(可选的KV数据库):支持键的查询、组合件的查询,还有复杂的查询。

不同账本的状态数据库存放在不同的目录下,不同链码的数据是按链码编号(chaincodeID)作为命名空间来划分数据。

状态数据库的基本操作是基于键值对的管理。读取状态数据的时候不用指定版本,读取到的状态数据是某个时刻最新的版本,返回的数据包含版本和数据两个部分。


worldStatus.png
  • 信息描述:状态数据库W包含两条数据。第一条,key=CAR1,value=Audi,版本=0.第二条,key=CAR2,value为一条复杂json表达式,版本也是0.

上述图片描述了世界状态数据库的基本存储结构。当发生交易后,改变数据内容,并变更版本号。

历史数据(History Database)

历史数据记录了每个状态数据的历史信息,历史信息是保存在LevelDB数据库中的。