深度探索区块链/分布式账本存储(5)

一。概述

深度探索区块链/分布式账本存储(5)_第1张图片

深度探索区块链/分布式账本存储(5)_第2张图片 

二。读写集

(一)。交易模拟和读写集

深度探索区块链/分布式账本存储(5)_第3张图片

      深度探索区块链/分布式账本存储(5)_第4张图片

(二)。交易验证和世界状态更新

深度探索区块链/分布式账本存储(5)_第5张图片

(三)。模拟和验证示例

 深度探索区块链/分布式账本存储(5)_第6张图片

三。账本编号

超级账本支持多账本(详细内容参考第7章实现数据隔离的多链及多通道),每个账本的数据是分开存储的。

账本编号(LedgerID)的数据存储在LevelDB数据库中,只是记录了有哪些版本,创建新的账本会检查是否有相同的账本编号存在,

这保证了全局唯一性。账本编号库并不存储与区块相关的数据。这和区块索引不一样。

四。账本数据

账本数据(Ledger)是以二进制文件的形式存储的,每个账本数据存储在不同的目录下。

后面内容都是在已经区分了账本的情况下再对数据进行查询的。

基于文件系统的区块存储实现了如下功能接口。

【1】。账本存储管理

A。提交区块到账本(AddBlock)

B。获取区块链信息(GetBlockchainInfo)

C。获取区块数据(RetrieveBlocks)

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】索引管理:跟踪区块和交易保存在哪个文件

(一)。账本数据存储

深度探索区块链/分布式账本存储(5)_第7张图片

深度探索区块链/分布式账本存储(5)_第8张图片

(二)。账本数据读取

深度探索区块链/分布式账本存储(5)_第9张图片

(三)。交易模拟执行

五。区块索引

深度探索区块链/分布式账本存储(5)_第10张图片

(一)。文件位置指针

     深度探索区块链/分布式账本存储(5)_第11张图片

深度探索区块链/分布式账本存储(5)_第12张图片

深度探索区块链/分布式账本存储(5)_第13张图片

(二)。索引的同步过程

六。状态数据

深度探索区块链/分布式账本存储(5)_第14张图片

(一)。LevelDB

    

深度探索区块链/分布式账本存储(5)_第15张图片

(二)。CouchDB

深度探索区块链/分布式账本存储(5)_第16张图片

        "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"

      },

      {

            深度探索区块链/分布式账本存储(5)_第17张图片

(三)基于状态数据的区块验证

七。历史数据

深度探索区块链/分布式账本存储(5)_第18张图片

历史信息记录最细的粒度就是交易,若在一个交易中多次对同一个writeKey更新数据,则会以第一次数据为准,历史信息实际存储的信息是固定的空字节数组[]byte{}。

更新区块信息的时候,会同步更新检查点信息,保存的内容是最新的区块高度和最大的交易序号,检查点信息用来判断历史信息的状态是否是最新的。

八。数据恢复

区块的提交过程分为3个步骤:

【1】。先保存区块到文件存储的账本数据中

【2】。然后更新状态数据

【3】。最后更新历史信息数据

这3个步骤是顺序执行的,在这个过程中有文件的操作,也有数据库的操作,所以在任何一个步骤都可能出现错误或者中断。恢复的过程会根据账本数据记录的区块信息和状态数据,历史信息数据的检查点进行比较,重新提交检查点之后的区块信息,保持账本数据的一致性。

本章小结:

本章介绍了Hyperledger Fabric 1.0的数据存储,包括账本数据(Ledger)、区块索引(Index)、状态数据(state Database)、历史数据(Hisotry database)等存储结构。目前的数据存储存在较大的优化空间,账本数据结构的设计带来的开销很大,最新的版本并没有实现账本载剪(Ledger Prune)功能,不能进行归档,也不能删除无效交易,所以会导致存储空间持续增长。

转载于:https://www.cnblogs.com/kaixinyufeng/p/9459786.html

你可能感兴趣的:(深度探索区块链/分布式账本存储(5))