Bigtable:结构化数据的分布式存储系统(二)

译自Bigtable_A Distributed Storage System for Structured Data

作者:Fay Chang, Jeffrey Dean, Sanjay Ghemawat, Wilson C.Hsieh, Deborah A. Wallach Mike Burrows, Tushar Chandra, Andrew Fikes, Robert E.Gruber

5 实现

Bigtable包括三个主要组件,分别是链接到客户端程序的库、Master服务器以及多个Tablet服务器。Bigtable可以动态地增删集群中的Tablet服务器,调整负载均衡。

Master服务器主要负责以下工作:为Tablet服务器分配Tablets、检测新加入的或过期失效的Tablet服务器、调整Tablet服务器的负载均衡以及对GFS上的文件进行垃圾收集。此外,Master服务器还负责处理对模式的相关修改操作,例如创建表和列族。

每个Tablet服务器都管理一个Tablet集合(每个服务器一般有几十个至上千个Tablet)。每个Tablet服务器负责处理其所加载的Tablet的读写操作,同时负责分割过大的Tablet。

和很多Single-Master类型的分布式存储系统相似,客户端读取的数据都不经过Master服务器,而是通过直接与Tablet服务器通信进行读写操作。因此,大多数客户端程序完全不需要和Master服务器通信,Master服务器的负载很轻。

一个BigTable集群存储了很多表,每个表包含了一个Tablet集合,而每个Tablet包含了某个范围内的行的所有相关数据。在初始状态下,一个表只有一个Tablet。随着数据的增长,表被自动分割成多个Tablet,缺省情况下,每个Tablet的大小约为100MB到200MB。

5.1 Tablet的位置

我们通过类似B+树的三层结构来存储Tablet的位置信息(图4)。

图4:Tablet位置层

第一层是存储在Chubby中的文件,文件包含了RootTablet的位置信息。Root Tablet包含特定元数据表中所有Tablet的位置信息。每个元数据Tablet包含一个用户Tablet集合的位置信息。Root Tablet是元数据表的第一个Tablet。RootTablet永远不会被分割,从而确保Tablet的位置信息存储结构不会超过三层。

在元数据表中,每个Tablet的位置信息都存放在一个行关键字下面,而这个行关键字是由Tablet所在表的标识符和Tablet的最后一行编码而成的。每一行元数据都存储了大约1KB的内存数据。在一个大小为128MB的元数据Tablet 中,采用这种三层结构的存储模式,可以标识2^34个Tablet的地址(如果每个Tablet存储128MB数据,则总共可以存储2^61字节数据)。

客户端库会缓存Tablet的位置信息。如果客户端程序没有缓存某个Tablet的位置信息,或发现缓存的地址信息不正确,则可以递归的方式在树状存储结构中查询Tablet的位置信息。如果客户端缓存是空的,则寻址算法需要通过三次网络来回通信寻址,包括一次Chubby读操作。如果客户端缓存的地址信息过期了,那么寻址算法最多可能需要6次来回网络通信才能更新数据,因为只有在缓存中查不到数据时才能发现数据过期(假设元数据Tablet不会频繁移动)。Tablet的地址信息是存放在内存中的,因此对地址信息的操作不必访问GFS文件系统。但我们一般会预取Tablet地址,从而进一步减少访问开销:每当需要从元数据表中读取一个Tablet的元数据时,都会多读取几个Tablet的元数据。

元数据表中还存储了次要信息,包括每个Tablet的事件日志(例如,服务器什么时候开始为该Tablet提供服务)。这些信息有助于排查错误和性能分析。

5.2 Tablet的分配

一个Tablet只能分配给一个Tablet服务器。Master服务器记录了当前活跃的Tablet服务器以及Tablet的分配情况。如果一个Tablet没有被分配且正好有一个Tablet服务器有足够的空闲空间装载该Tablet,Master服务器便会给向Tablet服务器发送装载请求,将Tablet分配给这个服务器。

Bigtable使用Chubby跟踪记录Tablet服务器的状态。Tablet服务器启动时会在Chubby的指定目录下建立一个唯一命名的文件,并获取该文件的独占锁。Master服务器实时监控该目录(服务器目录),及时发现Tablet服务器。如果由于网络中断丢失了Chubby上的独占锁,Tablet服务器便会停止为Tablet提供服务。(Chubby的高效机制能够确保Tablet服务器在不增加网络负担的情况下知道其是否还持有锁)。只要文件还存在,Tablet服务器就会试图重新获得对该文件的独占锁;如果文件不存在了,Tablet服务器就会自行退出,无法继续提供服务。Tablet服务器终止时(比如,集群的管理系统将运行该Tablet服务器的主机从集群中移除)会尝试释放它持有的文件锁,这样Master服务器就能尽快把Tablet分配到其它的Tablet服务器。

Master服务器负责检查Tablet 服务器是否已经停止为其Tablet提供服务;如是,则尽快重新分配其加载的Tablet。Master服务器通过轮询Tablet服务器文件锁的状态来检测Tablet服务器何时停止为Tablet提供服务。如果Tablet服务器报告丢失了文件锁或Master服务器最近几次尝试与其通信都没有得到响应,Master服务器便会尝试获取该Tablet服务器文件的独占锁。如果Master服务器成功获取了独占锁, 则说明Chubby处于正常运行状态,而Tablet服务器要么是宕机了、要么是不能与Chubby通信了。因此,Master服务器便会删除该Tablet服务器在Chubby上的服务器文件,确保其不再给Tablet提供服务。Tablet服务器在Chubby上的服务器文件被删除后,Master服务器便会把之前分配给该Tablet服务器的所有的Tablet放入未分配的Tablet集合中。为了确保Bigtable集群在Master服务器与Chubby之间的网络出现故障时仍然可以使用,Master服务器在其Chubby会话过期后便会主动退出。但Master服务器的故障不会改变现有Tablet在Tablet服务器上的分配状态。

集群管理系统启动Master服务器之后,Master服务器首先要了解当前Tablet的分配状态,然后才会修改分配状态。Master服务器在启动的时候执行以下步骤:

  1. Master服务器从Chubby获取唯一的Master锁,阻止创建其他Master服务器实例。
  2. Master服务器扫描Chubby的服务器文件目录,获取运行中的服务器。
  3. Master服务器与所有正在运行的Tablet服务器通信,获取每个Tablet服务器上Tablet的分配信息。
  4. Master服务器扫描元数据表获取所有的Tablet集合。扫描过程中,Master服务器发现还没有分配的Tablet时,便会将该Tablet加入未分配的Tablet集合,等待合适的时机进行分配。

在元数据Tablet被分配之前,扫描是无法进行的。因此,在扫描之前(步骤4),如果在第3步的扫描过程中发现RootTablet还没有分配,Master服务器便会把Root Tablet加入到未分配的Tablet集合,从而确保Root Tablet会被分配。由于RootTablet包含所有元数据Tablet的名称,因此当Master服务器扫描完Root Tablet后,就能得到所有METADATA表的Tablet名称。

只有出现以下事件时,现有Tablet集合才会改变:创建新表或删除旧表、两个Tablet被合并、一个Tablet被分割成两个小的Tablet。Master服务器可以跟踪记录所有这些事件,因为前两类事件都是由它启动的。Tablet分割事件需要特殊处理,因为这类事件是由Tablet服务器启动的。分割操作完成之后,Tablet服务器便会在元数据表中记录新的Tablet信息,完成提交;提交后,Tablet服务器便会通知Master服务器。如果没有把分割操作已提交的信息发送给Master服务器(可能Tablet服务器或Master服务器宕机了),Master服务器在要求Tablet服务器装载已经被分割的子表时便会发现新的Tablet。通过对比元数据表中Tablet信息,Tablet服务器会发现Master服务器要求其装载的Tablet并不完整,进而重新向Master服务器发送通知信息。

5.3 Tablet服务

如图5所示,Tablet的持久化状态信息保存在 GFS 上。更新操作提交到REDO日志中。在这些更新操作中,最近提交的操作存放在排序的缓存中,我们称之为memtable;较早提交的操作存放在一系列SSTable中。恢复Tablet时,Tablet服务器首先从元数据表中读取其元数据。元数据包括组成Tablet的SSTable列表以及一系列的Redo标点。这些标点指向可能含有该Tablet数据的已提交日志记录。Tablet服务器把SSTable的索引读进内存,使用在Redo标点之后提交的更新重建memtable。

图5:Tablet形式

对Tablet服务器进行写操作时,Tablet服务器首先要检查该操作格式是否正确、操作发起者是否有执行该操作的权限。权限验证的方法是从Chubby文件里读取有写权限的操作者列表(这个文件一般存放在Chubby客户端缓存中)。成功的修改操作会记录在提交日志中。可以通过批量提交的方式提高包含大量小修改操作的应用程序的吞吐量。写操作提交后,写的内容便会插入到memtable里。

对Tablet服务器进行读操作时,Tablet服务器会进行类似的完整性和权限校验。有效的读操作是在由一系列SSTable和memtable合并的视图里执行的。SSTable和memtable是按字母顺序排序的数据结构,因此可以高效生成合并视图。

进行Tablet合并和分割时,正在进行的读写操作能够继续进行。

5.4 压缩

随着写操作的执行,memtable不断变大。当memtable的大小到达阈值时,该memtable 便会会被冻结,然后创建一个新的memtable;被冻结的memtable会被转换成SSTable,写入GFS18。Minor 压缩过程有两个目的:一是缩减Tablet服务器使用的内存;而是在服务器灾难恢复过程中,减少必须从提交日志里读取的数据量。在压缩过程中,正在进行的读写操作仍能继续进行。

每一次Minor 压缩都会创建一个新的 SSTable。如果Minor 压缩过程不间断地持续进行下去,读操作可能需要合并来自多个SSTable的更新。为了限制合并文件的数量,我们会定期在后台执行Merging 压缩过程。Merging 压缩过程读取一些SSTable和memtable的内容,合并成一个新的SSTable。Merging压缩过程完成后,输入的这些SSTable和memtable就可以删除了。

将所有SSTable合并成一个新SSTable的过程叫作Major 压缩。由非Major 压缩产生的SSTable可能含有特殊的删除条目,这些删除条目收录了依然有效的原有SSTable中的已删除数据。而Major 压缩过程生成的SSTable不包含已经删除的信息或数据。Bigtable循环扫描所有的Tablet,并定期对Tablet执行Major 压缩。Major 压缩机制允许Bigtable回收已删除数据占有的资源,并且确保Bigtable能及时清除已删除的数据,这对存放敏感数据的服务来说非常重要。

参考资料

  1. Fay Chang, Jeffrey Dean, Sanjay Ghemawat, Wilson C.Hsieh, Deborah A. Wallach Mike Burrows, Tushar Chandra, Andrew Fikes and Robert E.Gruber. Bigtable_A Distributed Storage System for Structured Data

  2. Yan Wei. Google Bigtable中文版

转载于:https://juejin.im/post/5cef9c85f265da1b695d426f

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值