在介绍了BigTable的存储模型之后,本篇将重点给大家介绍其分布式模型。由于本文大多数内容参考BigTable的论文,如果有些博友已经熟读这篇论文,可以跳过本文。
从分布式的角度而言,BigTable会涉及总共五种独立的构件:
虽然Chubby并不是BigTable的一个组成部分,但由于其对BigTable整个分布式的运作非常关键,所以下面将首先介绍Chubby。
Chubby的机制
主要可以分为下面这四个方面:
Chubby在BigTable的作用
在BigTable中Chubby主要完成下面的几个任务:
假设Chubby服务在长时间内无法被访问,这将导致BigTable无法正常工作。还有,Chubby也有相关的开源版本,比如Hadoop系列的zookeeper,但两者在实现机制上面有一定的差别。
首先,在Master和Tablet节点之间的关系上面,采用了很多Single-Master类型的分布式存储系统类似的设计,也就是客户端读取的数据都不经过Master服务器,客户程序直接和Tablet服务器通信进行读写操作。由于BigTable的客户端程序不必通过Master服务器来获取Tablet的位置信息,因此,大多数客户端程序甚至完全不需要和Master服务器通信。在实际应用中,Master服务器的负载是很轻的,所以一个Master节点能支持上千的Tablet节点。还有,一个BigTable集群会存储了很多表,每个表都可以被认为是一个Tablet的集合,而且每个Tablet包含属于某个Range的行的所有相关数据,在初始状态下,一个表只有一个Tablet,但随着表中数据的增长,它会被自动分割成多个Tablet,在缺省情况下,每个Tablet的大小在100MB左右。下图为Tablet的层次图:
图1. Tablet的层次图
总体而言,Tablet的层次是一个三层,类似于B+树的结构。最上面是一个存储在Chubby中的文件,它包含了Root Tablet的位置信息。Root Tablet包含了一个特殊的METADATA表里所有的Tablet的位置信息。METADATA表的每个Tablet包含了一个UserTablet的集合。Root Tablet实际上是METADATA表的第一个Tablet,只不过对它的处理比较特殊,比如,Root Tablet永远不会被分割,这样将保证了Tablet的结构最多有三层。在METADATA表里面,每个Tablet的位置信息都存放在一个行关键字下面,而这个行关键字是由Tablet所在的表的标识符和Tablet的最后一行编码而成的。METADATA的每一行都存储了大约1KB的内存数据。在客户端使用的BigTable库会缓存Tablet的位置信息。如果客户端程序没有缓存某个Tablet的地址信息,或者发现它缓存的地址信息不正确,客户端程序就在上面那个树状的存储结构中递归的查询Tablet位置信息。在支撑的容量方面,一个大小适中的、容量限制为128MB的METADATA Tablet中,假如采用这种三层结构的存储模式,可以标识2^34个Tablet的地址(如果每个Tablet存储128MB数据,那么一共可以存储 2^61字节数据)。
Masater会跟踪当前有那些活跃的Tablet服务器和跟踪Tablet的存储地方,并将Tablet分配给有空闲空间的Tablet服务器。BigTable系统使用Chubby服务来记录Tablet服务器的状态。当一个Tablet服务器启动时,这个Tablet服务器会在Chubby的一个指定目录下建立一个有唯一性名字的文件,并且获取该文件的独占锁。Master服务器实时监控着这个目录,而且通过这个手段,Master服务器因此能够获知有那些新的Tablet服务器加入整个集群。如果这个Tablet服务器丢失了Chubby上的独占锁,只要那个文件还存在,这个服务器就会试图重新获得对该文件的独占锁;如果文件不存在了,那么Tablet服务器就不能再提供服务了,它会自行退出。当Tablet服务器终止时,它会尝试释放它持有的文件锁,这样一来,Master服务器就能尽快把Tablet分配到其它的Tablet服务器。
Master服务器会检查一个Tablet服务器是否已经不再为它的Tablet提供服务了,并且要尽快重新分配它加载的Tablet。 Master服务器通过轮询Tablet服务器文件锁的状态来检测。如果一个Tablet服务器报告它丢失了文件锁,或者Master服务器最近几次尝试和它通信都没有得到响应,Master服务器就会尝试获取该Tablet服务器文件的独占锁;如果Master服务器成功获取了独占锁,那么就说明Chubby是正常运行的,而Tablet服务器要么是宕机了、要么是不能和Chubby通信了,因此,Master服务器就删除该Tablet服务器在Chubby上的服务器文件以确保它不再给Tablet提供服务。一旦Tablet服务器在Chubby上的服务器文件被删除了,Master服务器就把之前分配给它的所有的Tablet放入未分配的Tablet集合中。为了确保Bigtable集群在Master服务器和Chubby之间网络出现故障的时候仍然可以使用,Master服务器在它的Chubby会话过期后主动退出。总体的来说,Chubby提供了一种高效的机制,利用这种机制,Tablet服务器能够在不增加网络负担的情况下知道它是否还持有锁。
当BigTable系统启动了一个Master服务器之后,Master服务器首先要了解当前Tablet的分配状态,之后才能够修改分配状态。 Master服务器在启动的时候执行以下步骤:
由于Root Tablet包括了所有METADATA的Tablet的名字,因此Master服务器扫描完Root Tablet以后,就得到了所有的METADATA表的Tablet的名字了。
保存现有Tablet的集合只有在以下事件发生时才会改变,建立了一个新表或者删除了一个旧表、两个Tablet被合并了、或者一个Tablet被分割成两个小的Tablet。Master服务器可以跟踪记录所有这些事件,因为除了最后一个事件外的两个事件都是由它启动的。Tablet分割事件需要特殊处理,因为它是由Tablet服务器启动。在分割操作完成之后,Tablet服务器通过在METADATA表中记录新的Tablet的信息来提交这个操作;当分割操作提交之后,Tablet服务器会通知Master服务器。如果分割操作已提交的信息没有通知到Master服务器(可能两个服务器中有一个宕机了),Master服务器在要求Tablet服务器装载已经被分割的子表的时候会发现一个新的Tablet。通过对比METADATA表中Tablet的信息,Tablet服务器会发现Master服务器要求其装载的Tablet并不完整,因此,Tablet服务器会重新向Master服务器发送通知信息。
本文结束,下篇将关注BigTable的功能集。
参考资料: