在YunTable正式开源前,本文将对YunTable0.8版在分布式方面新的设计进行重点讨论,而且本文将分为三个部分:分布式的意义、0.2版的设计和0.8版的设计。
什么是分布式,或者说分布式设计到底是为了满足什么目标,在我看来有三点非常关键,那就是:
但是,同时也要注意的是,那就是我们在设计分布式的时候,没有必要任何事都以Google的设计和理念为准绳,因为我们所面对和处理的需求不是与Google同一量级的,所以在设计上,可以多做一点的假设,比如,没有必要涉及多个数据中心之间的备份和一致性,或者可以限定一个集群的大小在1000台以内等,这些都对简化分布式架构有着非常重要的影响。
关于0.2版的设计,具体细节可以查看本系列之前的那篇《YunTable - 云时代的BigTable》其中的架构部分。简单的来说,Master节点只负责维护Table和Region节点之间的对应关系,而实际数据的查询和输入则都通过Region节点和Client端之间的交互完成,与Master节点无关。但现有的设计做了过多的假设,其中最关键的有两点:其一是就是假设一切运行正常,比如,服务器不会宕机,网络并不会中断等;其二是假设一个Column Family所存储的数据不会超过一块硬盘的容量,比如1TB。所以,从理论而言,现有的设计只是作为项目初期的过渡而已,所以需要在现有的设计进行更新,这就引出了下面0.8版的新设计。
关于这个新的设计,其目标是在Master节点能长时间稳定运行,并能快速从灾难中恢复的情况下在理论上能够支撑海量数据,应对各种失败情况和简化的管理,并且通过在今后的开发和使用当中对其进行不断地优化和更新,以使其分布式完备(Complete)。接下来,将给大家深入介绍整个新的分布式设计。
首先,在Master节点上,除了之前Table和Region节点之间的对应关系之外,Master节点还为每个Table维护一组Replica队列,这组队列的具体数目由配置文件中预先设定的备份数确定,如果用户没有在配置文件中输入,程序会使用其默认值,也就是3。在每个队列中将包括整个Table从创建开始到现在所有的数据,如果一个Table的数据大小超过一个Region节点的承载量,那么这个队列将包括多个Tablet,但只有这个队列的最后一个Tablet是用于新数据的插入,当然所有节点都参与查询操作,比如,在下图中,Replica1这个队列有Tablet0@Region1和Tablet3@Region3组成。
图1. Replica队列
接下来,将通过两个流程来对新的设计进行介绍。
流程1. 初始化
Master节点会根据预先设定的备份数来创建相应数目的Replica队列,并且给每个Replica队列添加一个Tablet,同时给这个Tablet设置一个初始的Timestamp。如果在初始化时,出现资源不够的情况,系统会报错,而且Replica队列的数目在初始化后不可更改。
流程2. Region节点出现问题
Region节点主要会出现两大类问题:其一是硬盘空间接近饱和;其二是这个节点失效,也就是无法通过网络来和它进行通信。这两类问题可以由Client端发现或者通过Master节点固定时段(默认为10分钟)的轮询来发现,并都交给Master节点的相应的逻辑来处理。
当Master节点确认这个Region节点出现问题时,它首先会搜寻那些Tablet和这个Region节点相关,之后将通过轮询来处理这些Tablet,在处理时,每个Tablet主要分为两类情况处理:
流程2.1 空间不足
如果之前Region节点的问题是空间不足的话,那么将这个Tablet的结束Timestamp设为当前时间来说明其在当前时间之后不再接受新数据的插入,同时在一个空闲空间较多的Region节点上创建一个新的Tablet,并将其初始Timestamp设为当前时间,并将其插入至之前那个Tablet所属的Replica队列的尾部,以用于新数据的插入。 注意,由于Master节点不会将最新Replica队列信息回送给Client端,而是由Client端来获取最新的信息,所以一些Client端会依旧在一段时间内将数据发给旧的Tablet,所以当读取转换那段时间(一般为10分钟)的数据,会同时参考新旧这两个Tablet。
流程2.2 节点失效
如果那个Region节点的问题是失效的话,那么就比较复杂,首先,要找出这个Tablet(如下图Table0@Region1)所包含数据在另一个Replica队列中对应的Tablet(如下图Table2@Region2),并且确保这个Tablet所属的Region节点是健康的。接着,在一个空闲空间较多的Region节点上创建一个新的Tablet(如下图Table0@Region4),并让刚才找到存有数据的Tablet和新的Tablet进行同步数据的操作,包括对应数据的Timestamp设定。还有,如果和下图不同的是,之前那个Tablet属于正在接受新数据的话,那么将像流程2.1那样再创建一个Tablet用于新的数据的插入,而之前那个新创建的Tablet只用于保存之前丢失或者失效的数据。
图2. 节点失效后的Replica队列