Peer节点使用leverDB这个数据库
Blockfile_mgr.go中定义了检查点(checkpointInfo)的结构
block的存储状态信息和block数据自身是分开存储的:当前block块的存储状态存储在leveldb数据库中,block块数据自身则存储在称为blockfile的文本文件中。
每在blockfile中存储一个block数据包,都会在leveldb中存储该block数据包对应的检查点,检查点以blkMgrInfoKey为key,checkpointInfo为value,组成一个键值对存储在leveldb中。
var (
blkMgrInfoKey = []byte("blkMgrInfo")
)
type checkpointInfo struct {
latestFileChunkSuffixNum int //记录block所在blockfile的文件名后缀
latestFileChunksize int //记录当前blockfile最新的大小
isChainEmpty bool //标识当前账本是否为空
lastBlockNumber uint64 //记录账本当前最新block的序列号
}
也就是说,leveldb用于存储当前账本的block数据的保存状态信息,这些信息主要指block的位置,长度信息,当前blockfile文件大小,index信息等,主要是用以定位block在blockfile中的所在位置,而blockfile文件保存实际的block数据。基本的操作方式也是根据leveldb中的信息去blockfile中对block进行读写操作,两者相互配合,共同保证block存储的完整性。
写入一个block,要涉及到的所有步骤:
◎block → blockfile
◎检查点信息 →levelDB
◎索引 →levelDB
◎索引检查点 →levelDB
1,写入block到blockfile
2,当写入一个block完成后,立即写入block检查点信息:先创建一个新的检查点对象B,然后根据现有的检查点对象A和写入的block数据包填充B,然后用B覆盖掉A。检查点的作用主要用在记录当前账本保存的状态,也就是说账本保存到哪里了,保存到哪个block了。
3,写入索引到levelDB
4,索引检查点会在每批的索引的最后写入,也即当索引检查点存在,则当批索引一定存在。索引的作用主要在于为调用者提供多种查找具体block或交易数据的方式。
在写入一个block时涉及到多个、多类数据,并先后写入,所以存在当系统崩溃时,数据部分写入的情况。因此在重新启动系统时,需要对部分写入的数据进行修补和同步。同步时,遵循的一个隐含的规则是前面的数据未写入,则后边的数据肯定没有写入。存在以下四种情况:
A,1没有完成
B,1完成2没有完成
C,12完成3没有完成
D,123完成4没有完成
A:取出的检查点信息是上一个block的检查点信息,因此会删除不完整的block
B:用现在新的block更新检查点信息,即重复步骤234
C:继续步骤34
D:继续步骤4
转载请注明来源