0. Abstract
Bigtable是一个存储pb量级结构化数据的分布式存储系统。google内部很多项目都在使用Bigtable,包括web indexing、Google Earth、Google Finance等,这些应用在数据大小、延迟要求等方面对Bigtable的要求各不相同。Bigtable成功的提供了一个灵活的、高性能的解决方案。本篇论文描述了Bigtable提供的数据模型,以及Bigtable的设计与实现。
1. Introduction
主要是一些概括性的内容,以及对后面各节主要内容的概况。
2. Data Model
Bigtable是一个稀疏的、分布式的、持久化的多维度有序map。这个map被row key、column key和一个时间戳索引,map的每个value是未解析的字节数组,即:
(row:string, column:string, time:int64) -> string
row key是任意的字符串(目前的上限是64KB,对于大部分使用者而言10-100 bytes够了)。单个row key下的单次读或者写是原子的(即使是不同的column),这样设计的原因是为了让客户清楚并发更新相同row时的系统行为。
Bigtable按照row key的字典序保存数据。表的row range动态分区,每个row range被称为tablet,是分布和负载均衡的单位。因此,对short row range的读取很高效,一般仅需要和少部分机器进行通信。客户可以利用这个性质,通过选择合适的row keys达到对数据访问良好的局部性。
column keys被组织为column families,是控制的基本单位。保存在同一个column family的所有数据往往拥有相同的类型,一个表中支持较少的column families(最多几百个),并且很少改变。相反的,一个表可以拥有的column没有上限(从设计上来说)。
一个column key的名字使用如下语法:family:qualifier。column family的名字必须是可打印的,而qualifiers可以是任意字符串。
timestamps是一个64-bit的整数。Bigtable中可以保存一份数据的多个版本;这些版本通过timestamps索引。timestamps可以由Bigtable赋值(real time),也可以由客户应用显式指定。需要避免冲突的应用需要自己产生唯一的timestamps。不同版本的数据按照timestamp降序存储。
为了更轻松的管理多个版本的数据,Bigtable支持两种垃圾回收策略(在单个column-family内部)。基于时间的和基于数量的,在此不赘述,见论文原文。
3. API
Bigtable提供了创建和删除table以及column families的函数,也提供了改变集群、table和column family元数据的函数,比如访问控制权限。
Bigtable支持单行事务,可用来执行原子的读-修改-写操作,但不支持跨行事。本节其他部分略过,见原文。
4. Building Blocks
Bigtable建立在Google其他的基础设施上,比如使用GFS存储日志和数据文件。Bigtable也依赖于集群管理系统来调度任务、管理机器和资源、存储机器错误、监控机器状态等。
Bigtable的数据使用Google SSTable文件格式存储。一个SSTable提供了持久的、有序的不可变kv map,并且key和value都是任意字符串。每个SSTable内部含有一系列block(每个block一般是64kb,当然这是可配置的)。SSTable的最后存储有block index,可用来定位block。
Bigtable依赖于一个高可用的、持久化的分布式锁服务Chubby(应该是一个类似于zk的系统,这里不赘述),Bigtable使用它确保master的唯一性;存储数据的bootstrap location(见5.1);发现tablet服务和确定tablet服务death(见5.2);存储Bigtable的架构信息(每个表的column family信息);存储访问权限列表。
5. Implementation
Bigtable分为三个组件:一个master服务、多个tablet服务、和一个连接客户端的library。tablet服务可以被动态添加以适应工作负载的变化。接着简要介绍了master服务和tablet服务的工作,见原文。
5.1 Tablet Location
使用类似于B+树的三层结构存储tablet位置信息。
第一层是一个存储在Chubby的文件,该文件含有root tablet的位置。root tablet包含了表METADATA所有的tablet位置信息。每一个METADATA tablet包含了一组用户tablet的位置信息。root tablet就是METADATA表的第一个tablet,但其特殊之处在于,它永远不会分裂(split),以确保位置信息的层次不超过三层。
METADATA的格式是这样的:row key由用户table identifier和其最后一个row编码而成。每个METADATA row存储了大约1KB的数组在内存中。对于大小限制在128MB的METADATA tablet,上述的三层架构可以存储2的34次方个tablet的位置信息。
5.2 Tablet Assignment
在同一时间,每个tablet被分配给一个tablet server。master跟踪着工作中的tablet server集合,以及当前tablet的分配情况。当一个tablet未被分配,且一个tablet server有足够的空间时,master会将这个tablet分配给该server。
Bigtable使用Chubby跟踪tablet servers。这里主要是Chubby的使用,类似于zk。只要tablet server工作期间,都会尝试去获取Chubby上一个文件上的排他锁,如果tablet server退出服务,它会尝试释放该锁,故master将会更快的分配其管理的tablets。
master负责检测一个tablet server何时不再为其tablets提供服务,并尽快重新分配这些tablets。master周期性的和其他tablet servers通信,询问其锁的状态。如果一个tablet server回复它丢失了它的锁,或者master无法和tablet server进行通信,master会尝试获取该tablet server上的排他锁。如果master成功获取了锁,则master通过删除该server的文件来确保该server无法继续提供服务。当一个server的文件被删除后,master移除之前分配给该server的所有tablets,并将这些tablets放入未分配tablets集合中。为了使得Bigtable集群不易受到mastre和Chubby之间网络问题的影响,如果Chubby session失效,master则会kill itself。如上所述,master的失败不会改变tablets的分配情况。
当一个master被集群管理系统启动时,它需要检查当前tablet的分配情况,在它可以修改这些内容前(英文翻中文好别扭)。master会在启动过程中依次执行以下步骤。(1)master获取Chubby上一个唯一的master lock,这个机制保证了不会有多个master同时存在。(2)master扫描Chubby上的服务目录,以寻找活着的server。(3)master和每个tablet server通信,获取该server上已经有哪些tablet了。(4)master扫描表METADATA以获得tablets的集合,如果发现某个tablet没有被某个tablet server获取,则将其放入unassigned tablets,便于后续tablet分配。
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。