http://www.7klian.com

Vite存储层设计详解之blockDB文件系统设计

文件列表在顺序写入和批量顺序读取上有很好的机能,这个特性在"账本同步"的场景中很是有用。

blockDB利用文件巨细牢靠的小文件列表来存储block数据,每个文件对应上面ringBuffer中的一个段,文件名既是前面ringBuffer中的标志fileId。通过按期的flush操纵,ringBuffer中的已利用段会被依次写入文件系统,已flush的段会成为空闲段。

1.写入数据的提交

为了便于提高效率,淘汰开发和接纳缓存区的开销,这里会将这些持续段拼接成一个称为ringBuffer的虚拟环,新数据追加到环的末端(Tail),旧数据从队头(Head)弹出,追加和弹出的操纵都是通过移动段下标的方法来完成的,队头和队尾之间的为待flush的已利用段,其他部门的段为可以被包围的空闲段。

序列化后的数据并不会直接写入文件,而是写入一个称为ringBuffer的内存缓冲区,这个缓冲区由持续的10M的子数据段(Segment)组成,每个数据段有对应的递增序列号fileId。对付每个Block,首先会写入该Block序列化后的字节长度值,后头才是真正的数据内容。因为Block和段不是一一对应,就会存在一个Block的数据需要跨段的问题,为了可以或许定位和存储一个Block数据段,通过[fileId, offset]二元组定位一个Block的起始位置,个中offset为该Block在该段中的offset。

今朝利用snappy算法做数据压缩,对每个block举办压缩。

在短期写入ring buffer的数据高出flush速度时,会导致数据高出ring buffer现有容量,ring buffer会自动扩容,待数据慢慢写入文件列表后,ring buffer会自动收缩到初始容量。

随机读取一个block操纵首先会通过blockDB索引获取[fileId, offset]二元组,然后按照fileId实验在ringBuffer中定位段,假如失败,在通过fileId打开对应的小文件,并seek到offset位置,从该位置的开头读取数据巨细后,,就可以持续读取该Block对应的数据块,这时候大概会涉及到要跨文件读取fileId+1的下一个小文件。因为回收了小文件来存储,seek操纵对比大文件来说会快许多,而且对付系统的页缓存也较量友好。

回滚数据分为预删除和删除两个阶段。在预删除阶段,先在ring buffer中删除对应数据,然后标志需要删除到的方针位置,标志完后这段数据已不行读,但并未被真正删除。在下次"异步批量Flush"时,开启删除阶段,这时会真正删除文件列表中的数据。

blockDB只支持将数据从最新状态删到某个汗青状态,不答允删除中间一段汗青数据,即数据是一个持续片断,不答允有数据空洞。

已利用段的数据被用作写缓存,同时也可以做读缓存,空闲段的数据假如之前曾经写入过有效数据,则也会被当做读缓存,因此整个ringBuffer都可以被用来做读缓存。整个ringBuffer相当于是一个最近写入数据的read-write buffer。

3.文件列表、随机读取及账本同步

blockDB用来存储生意业务(Transaction/AccountBlock)、快照(SnapshotBlock)数据,这两种数据范例在一个快照生成时都是一个最终确认的状态,写入后无需修改,因此很是适合通过快速追加写入的方法举办高效率的存储。blockDB的存储就是凭据追加写入优化的思路举办设计的,通过ringBuffer将需要顺序写入的数据依次写入一个行列,然后异步地批量写入文件。

一个SnapshotBlock和关联的AccountBlock列表会作为一个整体提交到存储层举办存储,存储层依次遍历AccountBlock和他们关联的SnapshotBlock,对相关数据布局举办序列化,然后写入存储。

4.数据回滚

5.数据压缩

2.ringBuffer

郑重声明:本文版权归原作者所有,转载文章仅为传播更多信息之目的,如作者信息标记有误,请第一时间联系我们修改或删除,多谢。

说点什么吧
  • 全部评论(0
    还没有评论,快来抢沙发吧!

相关文章阅读