听小董谝存储 五

目录

序章         

第一章  纯内存版

1.1 初始化流程

1.2 读写流程

第二章 数据开始下刷

第三章 关于覆盖写

第四章 关于del


我爱glt

序章         

前面几章总地说明了一个存储系统的主要模块,之后又分别讲了portal和master模块的设计思想。但是我知道大家都有一种隔靴搔痒的感觉,因为存储系统的核心,数据具体是怎么组织在磁盘上的,读写的具体实现又是什么我们还一无所知。

在这一节,我会从零到一的构建一个存储层模块,详细的告诉大家存储的具体实现。

第一章  纯内存版

老鸟:首先咱们定几个要求

1模块对外提供get,set,delete操作。

2数据必须落到磁盘,断电后只允许丢失部分数据(当然这个部分的比例,越小越好)。

另外,我再给你提一个设计的大前提:数据的落盘肯定不能是用户来一个写请求,就落盘一次。

小菜:嗯,我懂,如果用户每来一个写请求,我就落盘一次,那延时就不用考虑了。咱们落盘的时候,就是把用户的随机写变成了顺序写。算了,这节课太难了,老师还是你讲吧。                             

老鸟:OK,开始吧。咱们的存储层整体是基于hash的。那就下面这个图一,谈谈你的看法吧。

                                                             

                                                                                       图一 hash存储

小菜:嗯这个我懂。图一表示了一个hash散列表。桶数为8,共有6个元素。其中DataB,DateE的hash值对8取余后是一样的。同理DataC,DataD,DataF也是一样的。Hash桶一般采用头插法来处理冲突的元素,所以上面是先写入DataB,然后才是DataE。

老鸟:不错。但是上面的终归只是逻辑图,那些Data具体是如何存放的我们还是不知道。你再看看图二,假定我们的data是按照ABCDEF的顺序写入的。

小菜:嗯嗯,我懂了,图二的意思是说,我们把data按照数据写入的时间,顺序写入内存,就是右边那个蓝色的块(我们给它起个名字就叫DataRegion)。右边每一个绿色的块,咱们就暂时叫item吧。

另外图一和图二里黄色的块有什么区别么?

老鸟:图一里黄色的块是逻辑数据,里面已经包含了value的信息。图二里面中间黄色的块只是一个索引块,指向了DataRegion里面的某个位置,黑色的hash块就是索引块的桶(左边的黑色长条我们给它起名叫KeyIndex)。

                                                  

                                                                                       图二 data按照时序排放

老鸟:OK,我们的第一版系统已经OK了。你说说系统的初始化流程,以及读写的流程以及优缺点吧。

OK初始化的时候,

1.1 初始化流程

先申请两块内存,一块作为索引块,也就是KeyIndex,长度为n;另一块单纯地就作为存储块,不划分格式,就是一块buff,作为DataRegion

1.2 读写流程

                                           

                                                                                       图三 kv的读写流程

小菜:读写流程还是比较简单的,如上图三,左边是读的流程,右边是写的流程。其实写流程说白了就是头插法,读流程也和hashmap的没有什么区别。但是目前的系统还有几个问题

1 都是内存的。一断电就没有了。

2 只有get,set,没有del

3 上面的流程,没有考虑写数据的时候,数据已经存在的情况。

老鸟:不错,能梳理出问题了。咱们一个一个解决。

第二章 数据开始下刷

                                                          

                                                                                       图四 数据下刷

小菜:关于图四,我完全看不懂,请解释。

老鸟:上一张纯内存版的问题在于,数据不能一直积在内存,一方面不安全,一方面内存容量也不够。所以咱们需要把内存的数据下刷到磁盘。这是背景。

图四的左半部分,其实就是图二,数据都写到内存里,现在按照时间顺序写入的是ABCDEF。当检测到内存里的数据到达某个阈值了,就开始按照写入的时间顺序选择一定体积的数据下刷。在上图的例子里,我们选择了ABC三个item。把ABC全部刷到磁盘里。同时在KeyCache里面分别记录ABC在磁盘上的具体偏移。同时,在这次的例子里,我们把ABC下刷到一起,我们把磁盘里DataABC三个数据块占据的空间叫一个Block。下刷大概就是这么个流程:从DataRegion里选择一个个item,让它们的总体积尽可能接近一个Block的数据长度而不超过它,然后把这些数据都复制到磁盘里来。一般情况下一个Block的长度是512KB(因此,咱们这个存储系统允许的value的最大长度就是512KB)。小菜,说说有两个索引之后的读写流程吧。

小菜:写流程不变。读流程其实也一样,就是之前的索引块都指向内存,现在有的索引块执行磁盘。另外我还有一个问题,图四,右半部分,DataRegion里面ABC已经下刷了,那数据怎么回收呢?

老鸟:你还记得循环队列是怎么实现的么?

第三章 关于覆盖写

                                                          

                                                                                       图五 数据已经存在时的写入

老鸟:其实所谓的数据覆盖写的问题就是如上图五。以数据B为例,它的数据长度是50字节,而且已经下刷到磁盘。现在我又一次set DataB,这次的数据长度是80字节。磁盘里的Data ABC 都已经写好了,那么怎么把DataB落盘呢?(上面图五表示已经更新了索引节点里面的指向到内存的DataRegion了)

小菜:不知道。

                                                            

                                                                                        图六 关于覆盖写

老鸟:如图六,看懂了么?

小菜:尼玛。看懂个毛线。

老鸟:之前不是已经把DataABC都已经下刷到磁盘了么,这次就把DataDEFB下刷到磁盘就OK。然后更新DataB的索引从block1到block2。说白了,不是覆盖之前的数据,而是另起炉灶,再改变索引。之前的脏数据后面再说。

老鸟:另外,图六表示的DataABC都已经下刷到磁盘了,那么即使DataABC还没有下刷到磁盘,又给DataRegion里面写了一个DataB。下刷的时候,也会忽略第一个老的DataB(因为现在DataB的索引块并没有指向DataRegion里面老的那个DataB)

第四章 关于del

Data的数据结构里有一个字段叫isDel,默认都是false。

所谓的del,就是给data里面的isDel字段赋值为true。

举个例子,在上图四里面,假如我已经删除了DataA。那么当我下刷的时候,第一步从DataRegion里面扫描数据的时候,就会忽略DataA。完成下刷后,也会删除DataA的索引节点。

老鸟:好了今天讲的东西已经不少了,就先到这来吧。来小菜,总结一下咱们现在还有几个遗留问题没有解决吧。

小菜:

  • 1 上图六右半部分,block1里面的DataB现在已经是脏数据了。怎么回收。
  • 2 索引节点感觉还有几个问题,但是我一时说不上来。
  • 3 断电了咋办,数据怎么恢复?
  • 4 block是怎么组织的,内存是怎么组织的。

老鸟:OK,咱们下次就来解决这几个问题。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值