YunTable开发日记(6)- BigTable的分布式模型(转载)

源地址:http://peopleyun.com/?p=741

在介绍了BigTable的存储模型之后,本篇将重点给大家介绍其分布式模型。由于本文大多数内容参考BigTable的论文,如果有些博友已经熟读这篇论文,可以跳过本文。

综述

从分布式的角度而言,BigTable会涉及总共五种独立的构件:

  1.  
    1. Client端的库:一个基于BigTable的应用会根据其所使用语言的不同,而选择不同的Client端库来访问一个BigTable系统。
    2. Chubby服务:一个高可用、分布式的锁服务,用于协调整个BigTable的运作。
    3. Master节点:分配Tablets给Tablet服务器、检测新加入的或者过期失效的Table服务器、并对Tablet服务器进行负载均衡、以及对保存在GFS上的文件进行垃圾收集。除此之外,它还处理与数据库Schema相关的修改操作,例如建立Table和Column Family。
    4. Tablet节点: 每个Tablet服务器都管理一个Tablet的集合(通常每个服务器有大约数十个至上千个Tablet)。每个Tablet服务器负责处理它所加载的Tablet的读写操作,以及在Tablets过大时,对其进行分割。
    5. GFS系统:GFS是一个分布式文件系统,其主要用于管理和备份那些用于存储Tablet的SSTable文件,但是其执行对于BigTable而言是透明的。

虽然Chubby并不是BigTable的一个组成部分,但由于其对BigTable整个分布式的运作非常关键,所以下面将首先介绍Chubby。

Chubby的介绍

Chubby的机制

主要可以分为下面这四个方面:

  1.  
    1. 在运行机制方面:一个Chubby服务包括5个活动的副本,也就是replica,其中的一个副本被选为Master,让其来处理请求。只有在大多数副本都是正常运行的,并且彼此之间能够互相通信的情况下,Chubby服务才被认为是可用的,而当有一个副本失效的时候,Chubby使用Paxos算法来保证副本的一致性。
    2. 在实现机制方面:Chubby主要提供了一个名字空间,里面包括了目录和小文件。每个目录或者文件都可被视为一个锁,而读写这些文件的操作都是原子的。
    3. 在与Client端交流方面:Chubby提供对Chubby文件的一致性缓存。每个Chubby客户程序都维护一个与Chubby服务的会话。如果客户程序不能在租约(Lease)到期的时间内重新签订会话的租约,这个会话就过期失效了。当一个会话失效时,它拥有的锁和打开的文件句柄都失效了。

Chubby在BigTable的作用

在BigTable中Chubby主要完成下面的几个任务:

  1.  
    1. 确保在任何给定的时间内最多只有一个活动的Master节点。
    2. 存储BigTable数据库的初始Root Tablet的位置(具体请看下面“如何定位Tablet”这段)
    3. 为Tablet服务器提高锁服务,以及在Tablet服务器失效时进行善后(具体请看下面“如何分配Tablet”这段)
    4. 存储BigTable的schema信息(和column family相关的)和ACL(访问控制列表)。

假设Chubby服务在长时间内无法被访问,这将导致BigTable无法正常工作。还有,Chubby也有相关的开源版本,比如Hadoop系列的zookeeper,但两者在实现机制上面有一定的差别。

如何定位Tablet?

首先,在Master和Tablet节点之间的关系上面,采用了很多Single-Master类型的分布式存储系统类似的设计,也就是客户端读取的数据都不经过Master服务器,客户程序直接和Tablet服务器通信进行读写操作。由于BigTable的客户端程序不必通过Master服务器来获取Tablet的位置信息,因此,大多数客户端程序甚至完全不需要和Master服务器通信。在实际应用中,Master服务器的负载是很轻的,所以一个Master节点能支持上千的Tablet节点。还有,一个BigTable集群会存储了很多表,每个表都可以被认为是一个Tablet的集合,而且每个Tablet包含属于某个Range的行的所有相关数据,在初始状态下,一个表只有一个Tablet,但随着表中数据的增长,它会被自动分割成多个Tablet,在缺省情况下,每个Tablet的大小在100MB左右。下图为Tablet的层次图:Bigtable distributed

图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字节数据)。

如何分配Tablet?

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服务器在启动的时候执行以下步骤:

  1.  
    1. Master服务器从Chubby获取一个唯一的Master锁,用来阻止创建其它的Master服务器的实例。
    2. Master服务器扫描Chubby的服务器文件锁存储目录,获取当前正在运行的服务器列表。
    3. Master服务器和所有的正在运行的Tablet表服务器通信,获取每个Tablet服务器上Tablet的分配信息,如果发现发现Root Tablet还没有分配,Master服务器就把Root Tablet加入到未分配的Tablet集合。这个附加操作确保了Root Tablet会被分配。
    4. Master服务器扫描METADATA表获取所有的Tablet的集合。在扫描的过程中,当Master服务器发现了一个还没有分配的Tablet,Master服务器就将这个Tablet加入未分配的Tablet集合等待合适的时机分配。

由于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的功能集。

转载于:https://www.cnblogs.com/licheng/archive/2010/09/09/1821908.html

猜你喜欢

转载自blog.csdn.net/weixin_34277853/article/details/92626813