Google Bigtable (中文版)

http://dblab.xmu.edu.cn/post/google-bigtable/php

Abstracthtml

        BigTable是一个分布式存储系统,它能够支持扩展到很大尺寸的数据:PB级别的数据,包含几千个商业服务器。Google的许多项目都存储在BigTable中,包括WEB索引、Google Earth 和Google Finance。这些应用对BigTable提出了大相径庭的需求,不管是从数据量(从URL到网页到卫星图像)而言,仍是从延迟需求(从后端批量处理到实时数据服务)而言。尽管这些不一样的需求,BigTable已经为全部的Google产品提供了一个灵活的、高性能的解决方案。本文中,咱们描述了BigTable提供的简单数据模型,它容许客户端对数据部署和格式进行动态控制,咱们描述了BigTable的设计和实施。web

中文关键词:谷歌;分布式存储系统;键值存储;数据库;云数据库;正则表达式

英文关键词:Google Bigtable;key-value store; database; cloud database;distributed storage system算法

1 Introduction数据库

        在过去的两年半时间里,咱们已经设计、实施和部署了一个分布式存储系统BigTable,来管理Google当中的结构化数据。BigTable被设计成能够扩展到PB的数据和上千个机器。BigTable已经达到了几个目标:普遍应用性、可扩展性、高性能和高可用性。Google的六十多款产品和项目都存储在BigTable中,包括Google Analytics和Google Finance,Orkut,Personalized Search,Writely和Google Earth。这些产品使用BigTable来处理不一样类型的工做负载,包括面向吞吐量的批处理做业以及对延迟敏感的终端用户数据服务。这些产品所使用的BigTable的簇,涵盖了多种配置,从几个到几千个服务器,而且存储了几百TB的数据。express

        在许多方面,BigTable都和数据库很类似,它具备和数据库相同的实施策略。并行数据库[14]和内存数据库[13]已经取得了可扩展性和高性能,可是BigTable提供了和这些系统不同的接口。BigTable不能支持完整的关系型数据模型,相反,它为客户提供了一个简单数据模型,该数据模型能够支持针对数据部署和格式的动态控制,而且能够容许用户去推理底层存储所展示的数据的位置属性。BigTable使用行和列名称对数据进行索引,这些名称能够是任意字符串。BigTable把数据视为未经解释的字符串,虽然,客户可能常常把不一样格式的结构化数据和非结构化数据都序列化成字符串。最后,BigTable模式参数容许用户动态地控制,是从磁盘得到数据仍是从内存得到数据。bootstrap

        本文第2部分详细描述了数据模型,第3部分大概介绍了用户API,第4部分简要介绍了BigTable所依赖的Google底层基础设施,第5部分描述了BigTable的实施方法,第6部分描述了咱们针对BigTable作的性能改进,第7部分提供了BigTable的性能衡量方法,第8部分给出了几个实例来介绍 Google如何使用BigTable,第9部分介绍了咱们在设计和支持BigTable过程当中获得的经验教训。最后,在第10部分介绍相关工做,第11部分给出结论。后端

2 Data Model数组

        一个BigTable是一个稀疏的、分布的、永久的多维排序图。咱们采用行键盘(row key)、列键(column key)和时间戳(timestamp)对图进行索引。图中的每一个值都是未经解释的字节数组。

(row:string, column string, time:int64)→string

        咱们在检查了相似BigTable的系统的多种应用之后,才决定采用这种数据模型。这里给出一个实际的例子来阐释为何咱们采用数据模型设计。假设咱们想要拷贝一个可能被不少项目都是用的、很大的网页集合以及相关的信息,让咱们把这个特定的表称为Webtable。在Webtable当中,咱们使用URL做为行键,网页的不一样方面做为列键,并把网页的内容存储在contents:column中,如图1所示。

Google Bigtable,厦门大学,厦门大学计算机系,数据库实验室,林子雨

1 存储了网页数据的Webtable的一个片断。行名称是反转的URL,contents列家族包含了网页内容,anchor列家族包含了任何引用这个页面的anchor文本。CNN的主页被Sports Illustrated和MY-look主页同时引用,所以,咱们的行包含了名称为”anchor:cnnsi.com”和”anchor:my.look.ca”的列。每一个anchor单元格都只有一个版本,contents列有三个版本,分别对应于时间戳t3,t5和t6。

Rows

        一个表中的行键,是任意的字符串(当前在尺寸上有64KB,虽然10-100字节是用户最经常使用的尺寸)。对每一个行键下所包含的数据的读或写都是一个原子操做,无论这个行中所包含的列的数量是多少。这种设计决定可使得当针对同一行发生并发更新行为时,用户很容易知道系统的行为。

        BigTable在行键上根据字典顺序对数据进行维护。对于一个表而言,行区间是动态划分的。每一个行区间称为一个Tablet,它是负载均衡和数据分发的基本单位。于是,读取一个比较短的行区间是很是高效的,通畅只须要和少数几个机器通信。用户能够利用这种属性,也就是说,用户能够选择分布具备局部性的行区间。例如,在Webtable中,经过对URL地址进行反转,属于同一个领域的网页都会被分组到连续的行中。例如,咱们在键com.google.maps/index.html下面存储com.google.maps/index.html中包含的数据。把来自同一个领域的数据彼此临近存储,使得一些领域分析更加高效。

Column Families

        列键被分组成称为“列家族”的集合,它成为基本的访问控制单元。存储在一个列家族当中的全部数据,一般都属于同一个数据类型(咱们对同一个列家族中的数据一块儿进行压缩)。数据能够被存放到列家族的某个列键下面,可是,在把数据存放到这个列家族的某个列键下面以前,必须首先建立这个列家族。在建立完成一个列家族之后,就可使用同一个家族当中的列键。咱们的意愿是,让一个表当中所包含的列家族的数量尽量少(至多几百个列家族),并且,在操做过程中,列家族不多发生变化。相反,一个表能够包含无限数量的列。

        列键采用下面的语法命名:family:qualifier。列家族名字必须是可打印的,可是,修饰符qualifier能够是任意字符串。好比,对于Webtable而言,有一个列家族是language,它存储了网页所用语言的信息。在language列家族中,咱们只使用一个列键,它存储了每一个网页语言的ID。Webtable当中另外一个有用的列家族就是anchor,这个列家族中的每一个列键都表明了一个单个的anchor,如图1所示。它的修饰符qualifier是引用网站的名称,这个单元格内容是连接文本。

        访问控制以及磁盘和内存审计是在列家族层面上进行的。以Webtable为例,这些控制容许咱们管理几种不一样类型的应用,一些应用负责增长新的基本数据,一些应用负责读取基本数据而且建立衍生的列家族,一些应用则只被容许浏览现有的数据(甚至,若是出于隐私保护考虑,没法浏览所有列家族)。

Timestamps

        在BigTable中的每一个单元格当中,都包含相同数据的多个版本,这些版本采用时间戳进行索引。BitTable时间戳是64位整数。BigTable对时间戳进行分配,时间戳表明了真实时间,以微秒来计算。客户应用也能够直接分配时间戳。须要避免冲突的应用必须生成惟一的时间戳。一个单元格的不一样版本是根据时间戳降序的顺序进行存储的,这样,最新的版本能够被最早读取。

        为了减轻版本数据的管理负担,咱们支持两种“每列家族”设置,它会告诉BigTable来自动垃圾收集(garbage-collect)单元格版本。用户能够设定只保存单元格中数据的最近n个版本,或者只保存足够新版本(好比只保存最近7天内的数据版本)。

        在咱们的Webtable实例当中,咱们为存储在contents:column中的网页设置时间戳,时间戳的数值就是这个网页的这个版本被抓取的真实时间。上面所描述的垃圾收集机制,容许咱们只保留每一个网页的最近三个版本。

3 API

        BigTable的API提供了删除和建立表和列家族的功能。它还提供了改变簇、表和列家族的元数据,好比访问控制权限。

        客户应用能够书写和删除BigTable中的值,从单个行中查询值,或者对表中某个数据子集进行遍历。图2显示了一段C++代码,它使用了RowMutation来执行一系列的更新(为了更好地理解这个例子,已经忽略了不相关的细节)。对Apply的调用,会执行一个针对Webtable的原子更新操做:它增长一个anchor到www.cnn.com中去,而且删除一个不一样的anchor。

// Open the tableTable *T = OpenOrDie(“/bigtable/web/webtable”);// Write a new anchor and delete an old anchorRowMutation r1(T, “com.cnn.www”);r1.Set(“anchor:www.c-span.org”, “CNN”);r1.Delete(“anchor:www.abc.com”);

 

Operation op;

Apply(&op, &r1);

图2: Writing to Bigtable.

        图3显示了一段C++代码,它使用了Scanner来遍历某个行中的全部anchor(厦门大学林子雨标注:中文能够翻译成“锚”)。客户端能够遍历多个列家族,而且有几种机制能够用来对一次扫描中所产生的行、列和时间戳的数量进行限制。例如,咱们能够对上面的扫描进行限制,让所产生的anchor所在的列与正则表达式匹配anchor:*.cnn.com,或者只产生那些时间戳距离当前时间10天之内的anchor。

Scanner scanner(T);

ScanStream *stream;

stream = scanner.FetchColumnFamily(“anchor”);

stream->SetReturnAllVersions();

scanner.Lookup(“com.cnn.www”);

for (; !stream->Done(); stream->Next()) {

printf(“%s %s %lld %sn”,

scanner.RowName(),

stream->ColumnName(),

stream->MicroTimestamp(),

stream->Value());

}

图3: Reading from Bigtable.

        BigTable支持几种其余的功能,容许用户以更加复杂的方式来操做数据。首先,BigTable支持单行事务,能够容许对存储在某个行键下面的数据执行原子的“读-修改-写”操做。BigTable当前不支持通用的跨行键的事务,虽然它在客户端提供了跨行键批量写入数据的接口。其次,BigTable容许单元格被用来做为整数计数器。最后,BigTable支持在服务器的地址空间内执行客户端提供的脚本。这种脚本是用称为Sawzall的语言开发的,这种语言是Google开发出来进行数据处理的。目前,基于Sawzall的API不容许客户端脚本对BigTable执行回写操做,可是,它确实容许不一样类型的数据转换、基于任意表达式的过滤以及针对不一样类型操做符的总结。

        BigTable能够和MapReduce[12]一块儿使用,MapReduce是Google开发的、用来运行大规模并行计算的框架。咱们已经书写了一个Wrapper集合,它容许BigTable被用来做为一个MapReduce做业的输入源或者输出目标。

 

4 Building Blocks

        BigTable是构建在其余几个Google基础设施之上的。BigTable使用了分布式Google文件系统(GFS[17])来存储日志和数据文件。BigTable的一个簇一般在一个共享机器池内进行操做,这个共享机器池会运行其余一些分布式应用。BigTable的进程一般和其余应用的进程共享一样的机器。BigTable依赖一个簇管理系统来调度做业、在共享机器上调度资源、处理机器失败和监督机器状态。

        Google SSTable文件格式做为存储BigTable数据的内部格式。一个SSTable提供一个持久化的、排序的、不可变的、从键到值的映射,其中,键和值都是任意的字节字符串。BigTable提供了查询与一个指定键相关的值的操做,以及在一个指定的键区间内遍历全部的“键/值对”的操做。在内部,每一个SSTable都包含一个块序列。一般,每一个块是64KB,不过块尺寸是可配置的。存储在SSTable结尾的块索引,能够用来快速定位块的位置。当SSTable被打开时,块索引就会被读入内存。一个查询操做只须要进行一次磁盘扫描,咱们首先在内存的块索引当中使用二分查找方法找到合适的块,而后从磁盘中读取相应的块。可选地,一个SSTable能够被彻底读入内存,这样,咱们在进行查找操做时,就不须要读取磁盘。

        BigTable依赖一个高可用的、持久性的分布式锁服务Chubby[8]。一个Chubby服务包含5个动态副本,其中一个被选做主副本对外提供服务。当大部分副本处于运行状态而且可以彼此通讯时,这个服务就是可用的。Chubby使用Paxos算法[9][23]来使它的副本在失败时保持一致性。Chubby提供了一个名字空间,它包含了目录和小文件。每一个目录和文件能够被用做一个锁,针对文件的读和写操做都是原子的。Chubby客户端函数库提供了针对Chubby文件的持久性缓存。每一个Chubby客户端维护一个session,这个session具有Chubby服务。若是租约过时之后不能及时更新session的租约,那么这个客户端的session就会过时。当一个客户端的session过时时,它会丢失全部锁,而且放弃句柄。Chubby客户端也能够注册针对Chubby文件和目录的回调服务(callback),从而通知session过时或其余变化。

        BigTable使用Chubby来完成许多任务:(1)保证在每一个时间点只有一个主副本是活跃的,(2)来存储BigTable数据的bootstrap的位置(见5.1节),(3)来发现tablet服务器,(4)宣告tablet服务器死亡,(5)存储BigTable模式信息(即每一个表的列家族信息),以及(6)存储访问控制列表。若是在一段时间之后,Chubby变得不可用,BigTable就不可用了。咱们最近对涵盖11个Chubby实例的14个BigTable簇进行了这方面的效果测试。因为Chubby的不可用(可能因为Chubby过期,或者网络故障),而致使一些存储在BigTable中的数据变得不可用,这种情形占到BigTable服务小时的平均比例值是0.0047%。单个簇的百分比是0.0326%。

5 Implementation

        BigTable实现包括三个主要的功能组件:(1)库函数:连接到每一个客户端,(2)一个主服务器,(3)许多Tablet服务器。Tablet服务器能够根据工做负载的变化,从一个簇中动态地增长或删除。主服务器负责把Tablet分配到Tablet服务器,探测Tablet服务器的增长和过时,进行Table服务器的负载均衡,以及GFS文件系统中的垃圾收集。除此之外,它还处理模式变化,好比表和列家族建立。

        每一个Tablet服务器管理一个Tablet集合,一般,在每一个Tablet服务器上,咱们会放置10到1000个Tablet。Tablet服务器处理针对那些已经加载的Tablet而提出的读写请求,而且会对过大的Tablet进行划分。

        就像许多单服务器分布式存储系统同样[17,21],客户端并非直接从主服务器读取数据,而是直接从Tablet服务器上读取数据。由于BigTable客户端并不依赖于主服务器来得到Tablet的位置信息,因此,大多数客户端历来不和主服务器通讯。从而使得在实际应用中,主服务器负载很小。

        一个BigTable簇存储了许多表。每一个表都是一个Tablet集合,每一个Tablet包含了位于某个域区间内的全部数据。在最初阶段,每一个表只包含一个Tablet。随着表的增加,它会被自动分解成许多Tablet,每一个Tablet默认尺寸大约是100到200MB。

5.1 Tablet Location

咱们使用了一个相似于 B+树的三层架构(如图4所示),来存储Tablet位置信息。

Google Bigtable,厦门大学,厦门大学计算机系,数据库实验室,林子雨

第一个层次是一个文件,存储在Chubby中,它包含了Toot Tablet的位置信息。Root Tablet把Tablet的全部位置信息都保存在一个特定的METADATA表中。每一个METADATA表都包含了一个user tablet集合的位置信息。Root Tablet其实就是METADATA表当中的第一个Tablet,可是,它被区别对待,它在任何状况下都不会被拆分,从而保证Tablet位置层次结构不会超过三层。

METADATA表存储了属于某个行键的Tablet的位置信息,所谓行键,就是关于Tablet表标识符和它的最后一行这两者的编码。每一个METADATA行,大约在内存中存储了1KB的数据。因为采用了128M大小的METADATA Tablet的适当限制,咱们的三层位置模式足够用来存放2的34此方的Tablet的位置信息。

客户端函数库会缓存Tablet位置信息。若是客户端不知道一个Tablet的位置信息,或者它发现,它所缓存的Tablet位置信息部正确,那么,它就会在Tablet位置层次结构中依次向上寻找。若是客户端缓存是空的,那么定位算法就须要进行三次轮询,其中就包括一次从Chubby中读取信息。若是客户端的缓存是过时的,定位算法就要进行六次轮询,由于,只有在访问无效的时候才会发现缓存中某个entry是过时的(这里假设METADATA Tablets不会频繁移动)。虽然,Tablets位置信息是保存在缓存中,从而不须要访问GFS,可是,咱们仍然经过让客户端库函数预抓取tablet位置信息,来进一步减小代价,具体方法是:每次读取METADATA表时,都要读取至少两条以上的Tablet位置信息。

咱们也在METADATA表中存储了二级信息,包括一个日志,它记载了和每一个tablet有关的全部事件,好比,一个服务器何时开始提供这个tablet服务。这些信息对于性能分析和程序调试是很是有用的。

5.2 Tablet Assignment

        在每回,每一个Tablet能够被分配到一个tablet服务器。主服务器跟踪tablet服务器的状况,掌握当前tablet被分配到tablet服务器的状况,其中包括哪一个tablet尚未被分配。当一个tablet没有被分配,而且一个具备足够空间能够容纳该tablet的tablet服务器是可用时,主服务器就把当前这个tablet分配给这个tablet服务器,主服务器会向tablet服务器发送一个tablet负载请求。

        BigTable使用Chubby来跟踪tablet服务器。当一个Tablet服务器启动的时候,它建立而且得到一个独占的排他锁,这个锁会锁住一个特定的Chubby目录中的一个惟一命名的文件。主服务器监视这个目录(服务器目录),来发现tablet服务器。若是一个tablet服务器中止服务,它就会丢失这个锁,好比,因为网络故障,致使这个tablet服务器丢失了这个Chubby会话。(Chubby提供了一个完善的机制,来容许一个tablet服务器检查本身是否已经丢失了这个独占排他锁)。若是丢失了锁,那么,只要目录中的这个文件还存在,那么一个tablet服务器就会努力去得到这个锁。若是文件再也不存在,那么,这个tablet服务器就再也不可以对外提供服务,所以,它就自杀。一旦一个tablet服务器终止了服务(好比,簇管理系统把这个tablet服务器从簇中移除),它就会努力释放锁,这样,主服务器就能够更快地从新分配这个tablet。

        主服务器须要探测,何时tablet服务器再也不提供tablet服务,而且要负责尽快对这些tablet进行从新分配。为了探测何时tablet服务器再也不提供tablet服务,主服务器会周期性地询问每一个tablet服务器,了解他们的锁的状态。若是一个tablet服务器报告,它已经丢失了锁;或者,在最近的几回尝试中,主服务器都没法与tablet服务器取得联系,主服务器就会努力得到一个针对这个服务器文件的独占排他锁。若是主服务器能够得到这个锁,那么,Chubby就是可用的,相应地,这个tablet服务器或者已经死亡,或者有些故障致使它没法到达Chubby。所以,主服务器就从Chubby中删除这个tablet服务器的文件,从而确保这个tablet服务器再也不可以提供服务。一旦一个服务器文件被删除,主服务器就能够把全部之前分配给该服务器的tablet,都移动到“待分配”tablet集合。为了保证一个BigTable簇不会轻易受到主服务器和Chubby之间的网络故障的影响,若是一个主服务器的Chubby会话过时了,这个主服务器就会自杀。可是,正如上所述,主服务器失效,不会改变tablet到table的分配。

        当一个主服务器被簇管理系统启动时,在它可以改变tablet分配以前,它必须首先了解当前的tablet分配信息。为此,在启动的时候,主服务器会执行如下步骤:(1)主服务器在Chubby中抓取一个独特的master lock,这就防止了多个主服务器并发启动的情形。(2)主服务器扫描Chubby中的服务器目录,从而发现当前可用的服务器。(3)主服务器和当前每一个可用的tablet服务器通讯,来发现哪些tablets已经被分配到哪一个tablet服务器。(4)主服务器扫描METADATA表来学习tablets表集合。一旦在扫描过程当中,主服务器发现某个tablet尚未被分配,主服务器就把这个tablet放置到“待分配”tablet集合,这就使得这些tablet能够进入待分配状态。

        一个比较复杂的状况是,在METADATA tablets被分配以前,咱们是不能扫描METADATA表的。所以,在开始扫描(步骤4)以前,若是主服务器在步骤3的扫描中发现root tablet没有被发现,主服务器把root tablet增长到待分配tablet集合。这个增长,保证了root tablet必定会被分配。由于,root tablet包含了全部METADATA tablets的名字。主服务器只有在扫描了root tablet之后,才可能知道全部这些METADATA tablets的名字。

        现有的tablet集合,只有在如下情形才会发生改变:(1)当一个tablet被建立或删除;(2)对两个现有的tablet进行合并获得一个更大的tablet;(3)一个现有的tablet被分割成两个较小的tablet。主服务器能够跟踪这些变化。Tablet分裂会被特殊对待,由于,它是由一个tablet服务器发起的。Tablet服务器经过把信的tablet信息记录在METADATA表中,来提交分裂操做。当分裂被提交之后,这个tablet服务器会通知主服务器。为了防止分裂通知丢失(或者因为主服务器死亡或者因为tablet服务器死亡),当主服务器要求一个tablet服务器加载已经被分裂的tablet时,主服务器会对这个新的tablet进行探测。Tablet服务器会把分裂的状况告知主服务器,由于,它在METADATA表中所找到的tablet entry,只能肯定主服务器要求它加载的数据的一部分。

5.3 Tablet Serving

Google Bigtable,厦门大学,厦门大学计算机系,数据库实验室,林子雨

一个tablet的持久化存储是存在GFS当中,如图5所示。更新被提交到一个提交日志,日志中记录了redo记录。在这些更新当中,最近提交的更新被存放到内存当中的一个被称为memtable的排序缓冲区,比较老的更新被存储在一系列SSTable中。为了恢复一个tablet,tablet服务器从METADATA表当中读取这个tablet的元数据。这个元数据包含了SSTable列表,其中,每一个SSTable都包括一个tablet和一个重作点(redo point)的集合,这些redo point是一些指针,它们指向那些可能包含tablet所需数据的重作日志。服务器把SSTable索引读入内存,而且重构memtable,方法是,执行重作点之后的全部已经提交的更新。

当一个写操做到达tablet服务器,服务器首先检查它是不是良好定义的,而且发送者是否被受权执行该操做。执行受权检查时,会从一个Chubby文件中读取具备访问权限的写入者的列表,这个Chubby文件一般总可以在Chubby客户端缓存中找到。一个有效的变化,会被写到提交日志中。分组提交是为了改进许多小更新[13,16]操做的吞吐量。在写操做已经被提交之后,它的内容就会被插入到memtable。

当一个读操做到达Tablet服务器,与写操做相似,服务器也会首先检查它是不是良好定义和获得受权的。一个有效地读操做是在如下两者的合并的基础上执行的,即一系列SSTable和memtable。因为SSTable和memtable是字典排序的数据结构,合并视图的执行是很是高效的。

当tablet发生合并或分解操做时,正在到达的读写操做仍然能够继续进行。

5.4 Compactions

        随着写操做的执行,memtable的尺寸逐渐增长。当memtable的尺寸到达一个门槛值的时候,memtable就被冻结,就建立一个新的memtable,被冻结的memtable就转化成一个SSTable,并被写入到GFS。这个“次压缩”(minor compaction)过程有两个目标:(1)它缩减了tablet服务器的内存使用率;(2)当发生服务器死亡须要恢复时,它减小了须要从重作日志中读取的数据量。当压缩过程正在进行时,正在到达的读写操做仍然能够继续进行。

        每一次小压缩都会建立一个新的SSTable,若是这种行为没有限制地持续进行,读操做可能须要从任意数量的SSTable中合并更新。相反,咱们会对这种文件的数量进行限制,咱们在后台周期性地运行一个合并压缩程序。一个合并压缩程序从一些SSTable和memtable中读取内容,而且写出一个新的SSTable。一旦压缩过程完成,这个输入的SSTable和memtable就能够被删除。

        一个合并压缩程序,把全部的SSTable的数据重写到一个SSTable,这个合并压缩被称为“主压缩”(major compaction)。非主压缩所产生的SSTable能够包含特殊的删除入口(entry),它把被删除的数据压缩在仍然存活的比较老的SSTable当中。另外一方面,一个主压缩过程,产生一个SSTable,它不包含删除信息或被删除的数据。BigTable按期检查它的全部tablet,并执行主压缩操做。这些主压缩过程能够容许BigTable收回被删除数据占用的资源,而且保证被删除数据在必定时间内就能够从系统中消失,这对于一些存储敏感数据的服务来讲是很是重要的。

6 Refinements

   之前章节所描述的实现,须要一系列完善措施从而得到高性能、可用性和可靠性,这些都是咱们的用户所要求的。这部份内容更详细介绍实现细节。

Locatity groups

        客户端能够把多个列家族一块儿分组到一个locality group中。咱们会为每一个tablet中的每一个locality group大都建立一个单独的SSTable。把那些一般不被一块儿访问的列家族分割到不一样的locality group,能够实现更高效的读。例如,在WebTable当中的页元数据(好比语言和校验码),能够被放置到同一个locality group当中,网页的内容能够被放置到另外一个locality group当中。那些想要读取页面元数据的应用,就不须要访问全部的页面内容。

        除此之外,一些有用的参数,能够针对每一个locality group来设定。例如,一个locality group能够设置成存放在内存中。常驻内存的locality group的SSTable,采用被动加载的方式被加载tablet服务器的内存,即只有应用请求SSTable中的数据,而这些数据又不在内存中时,才把SSTable加载到内存。一旦加载,属于这些locality group的列家族,就能够被应用直接访问,而不须要读取磁盘。这个特性对于那些被频繁访问的小量数据来讲是很是有用的。

Compression

客户端能够决定是否对相应于某个locality group的SSTable进行压缩,若是压缩,应该采用什么格式。用户自定义的压缩格式能够被应用到每一个SSTable块中(块的尺寸能够采用与locality group相关的参数来进行控制)。虽然对每一个块进行单独压缩会损失一些空间,可是,咱们能够从另外一个方面受益,当解压缩时,只须要对小部分数据进行解压,而不须要解压所有数据。许多客户端都使用“两段自定义压缩模式”。第一遍使用Bentley and McIlroy[6]模式,它对一个大窗口内的长公共字符串进行压缩。第二遍使用一个快速的压缩算法,这个压缩算法在一个16KB数据量的窗口内寻找重复数据。两个压缩步骤都很是快,在现代计算机上运行,他们编码的速度是100-200MB/S,解码的速度在400-1000MB/S。

当选择咱们的压缩算法时,即便咱们强调速度而不是空间压缩率,这个两段压缩模式也表现出了惊人的性能。例如,在WebTable中,咱们使用这种压缩模式来存储网页内容。在其中一个实验当中,咱们在一个压缩后的locality group当中存储了大量的文档。为了达到实验的目的,咱们只为每一个文档存储一个版本,而不是存储咱们能够得到的全部版本。这个压缩模式得到了10:1的空间压缩率。这比传统的GZip方法的效果要好得多,GZip针对HTML数据一般只能得到3:1到4:1的空间压缩率。这种性能上的改进,是和WebTable中的行的存储方式紧密相关的,即全部来自同一个站点的网页都存储在相近的位置。这就使得Bentley and McIlroy算法能够从同一个站点的网页中肯定大量类似的内容。许多应用,不仅是WebTable,都会很好地选择行名称,从而保证类似的数据能够被存放到同一个簇当中,这样就能够取得很好的压缩率。当咱们在BigTable中存储同一个值的多个不一样版本时,能够取得更好的压缩率。

Caching for read performance

   为了改进读性能,tablet服务器使用两个层次的缓存。Scan缓存是一个高层次的缓存,它缓存了“键–值”对,这些“键–值”对是由tablet服务器代码的SSTable接口返回的。Block缓存是比较低层次的缓存,它缓存了从GFS当中读取的SSTable块。Scan缓存对于那些频繁读取相同数据的应用来讲是很是有用的。Block缓存对于那些倾向于读取与本身最近读取数据临近的数据的应用来讲,是比较有用的,好比顺序读取,或者随机读取属于同一个locality group中的不一样的列。

Bloom filters

    正如5.3节阐述的那样,一个读操做必须从构成一个tablet的当前状态的全部SSTable中读取数据。若是这些SSTable不在内存中,咱们就不得不须要不少磁盘访问。咱们经过下面的方式来减小磁盘访问,即容许客户端来肯定,为某个特定locality group中的SSTable建立Bloom filter[7]。一个Bloom filter容许咱们询问,一个SSTabble是否包含属于指定的“行–列队”的特定的数据。对于某个特定的应用,一个用来存储Bloom filter的不多量的tablet服务器内存空间,均可以极大减小读操做的磁盘访问次数。咱们使用Bloom filter也意味着,许多针对目前不存在的行或列的查询,根本就不须要访问磁盘。

Commit-log implementation

        若是咱们为每一个tablet都设置一个单独的文件来保存提交日志,那么,在GFS中,会有大量的文件并发写操做。取决于每一个GFS服务器底层文件系统的实现方式,这些写操做会引发大量的磁盘访问。除此之外,让每一个tablet都有一个单独的日子文件,会下降分组提交优化的效率。为了解决这些问题,咱们对每一个tablet服务器具有一个独立日志文件这种方式进行了补充,不是把更新都写入相应tablet的独立文件中,而是把几个不一样tablet的更新内容都添加到一个一样的物理日志文件中[18][20]。

        使用单个日志文件,明显改善了普通操做时的性能收益,可是,它使得故障恢复变得复杂起来。当一个tablet服务器死亡,它上面承载的tablet会被从新分配到其余多个tablet服务器,每一个tablet服务器一般只接收一部分tablet。为了给一个tablet恢复状态,新的tablet服务器须要根据原来tablet服务器中记载的提交日志文件,为这个tablet从新执行一遍更新操做。可是,针对这些tablet的更新操做的日子记录,都混合存放在一个日志文件中。一种方法是,让新的tablet服务器完整地读取一份提交日志文件,而后,只把恢复这个tablet时所须要的日志记录读取出来,完成恢复。可是,在这种机制下,若是有100个机器,每一个都被分配了来自死亡tablet服务器的一个单独的tablet,那么,这个日志文件就必须被重复读取100遍。

        咱们经过如下的方式来避免日志的重复读写:首先以键(表,行名称,日志顺序号)的顺序对日志文件的条目(entry)进行排序。在排序获得的结果中,全部针对某个特定tablet的更新都是连续存放的,所以,能够经过一次磁盘寻找,而后顺序批量读取数据,这种方法具备较高的效率。为了实现并行排序,咱们把日子文本分割成64MB为单位的分段,在不一样的tablet服务器上对每一个分段进行并行排序。主服务器会对排序过程进行协调,当一个tablet服务器表示须要从一些提交日志文件中恢复数据时,就须要启动排序过程。

        书写提交日志到GFS中去,因为不少缘由(好比GFS服务器上包含不少冲突操做,或者网络拥塞),有时会带来性能上的瓶颈。为了使得更新免受GFS延迟的影响,每一个tablet服务器实际上有两个日子书写线程,每一个线程都书写到它本身的日志中。在运行时,只有一个进程处于工做状态。若是当前活跃的日志书写线程性能比较差,那么,就切换到另外一个日志书写线程。在更新日志队列中的更新就会被这个新激活的线程书写。日志条目包含了序号,这就能够帮助恢复过程删除那些因为线程切换而致使的重复的日志记录。

Speeding up tablet recovery

    若是主服务器把一个tablet从一个tablet服务器转移到另外一个tablet服务器。这个源tablet服务器就对这个tablet作一个次压缩(minor compaction)。经过减小tablet服务器中的提交日志中的未压缩状态的数量,压缩过程减小了恢复时间。在完成这个压缩过程之后,这个源tablet服务器就中止提供针对这个tablet的服务。在它实际上卸载这个tablet以前,这个源tablet服务器要作另外一个次压缩,来删除本tablet服务器的日志中任何未压缩的状态,这些未压缩状态是在第一个次压缩进行过程当中产生的。当第二个次压缩完成时,这个tablet就能够被加载到另外一个tablet服务器,而不须要任何日志条目的恢复。

Exploiting immutability

        除了SSTable缓存,BigTable系统的其余部分也已经被简化,这些简化基于这样一个事实,即咱们所产生的全部SSTable都是不变的。例如,当咱们从SSTable中读取数据时,不须要进行任何文件系统访问的同步。结果是,针对行级别的并发控制能够高效地执行。惟一发生变化的数据结构是memtable,它同时被读操做和写操做访问。为了减小读取memtable过程当中的冲突,咱们使得每一个memtable行采起”copy-on-write”,而且容许读和写操做并行执行。

        因为SSTable是不可变的,永久性删除数据的问题就转变成,收集废弃的SSTable。每一个tablet的SSTable,都会在METADATA表中进行注册。主服务器移除废弃的SSTable,把它标记为垃圾数据集合。

        最后,SSTable的不可变性,容许咱们更快地分裂tablet,而不是为每一个子tablet生成一个新的SSTable集合。咱们让子tablet和父tablet共享一个SSTable集合。

7 Performance Evaluation

        咱们创建了一个BigTable簇,它具备N个tablet服务器,咱们改变N的值,从而测试BigTable的性能和可扩展性。Tablet服务器的配置为,1GB内存,而且把数据写到GFS单元格中,这个GFS单元格包含了1786个机器,每一个机器具有400GB IDE硬盘。咱们让N个客户端机器产生针对BigTable的负载,从而实现测试。须要指出的是,这里咱们采用的客户端的数量和tablet服务器的数量是相等的,从而保证客户端不会成为瓶颈。每一个机器都有两个双核Opteron 2GHz芯片、足够的物理内存(从而可以容纳工做集产生的数据)和GB带宽的网络链接。这些机器被安排为两层树型交换网络,在根部的带宽能够达到100-200Gbps。全部这些机器都采用相同的配置,都在同一个域内,所以,任何两台机器之间的通信时间都不会超过1微秒。

        Tablet服务器、主服务器、测试客户端和GFS服务器都在同一个机器集合上运行。每一个机器都运行一个GFS服务器。同时,一些机器还会另外运行一个tablet服务器,一个客户端进程。

        R是BigTable的不一样值的行键的数量,在选择R的值的时候,须要确保每一个benchmark在每一个tablet服务器上读或写大约1GB的数据量。

        负责顺序写的benchmark,使用名称从0到R-1的行键。行键的空间被分区成10N个等尺寸区间。这些区间被中央调度器分配到N个客户端,一旦,某个客户端已经处理完前面分配到的区间后,中央调度器就当即给这个客户端分配另外一个区间。这种动态分配,能够减轻其余运行于当前机器上的进程对该机器的影响。咱们在每一个行键下面,写了一个单个字符串。每一个字符串都是随机生成的,所以,不具有可压缩性。除此之外,在不一样行键下面的字符串都是不一样的,这样就不会存在跨行压缩。负责随机写的benchmark也是相似的,初了行键在写以前要以R为模数进行哈希操做,从而使得在整个benchmark期间,写操做负载能够均匀分布到整个行空间内。

        负责顺序读的benchmark产生行键的方式,也和负责顺序写的benchmark相似。可是,顺序读benchmark不是在行键下面写数据,而是读取存储在行键下面的字符串,这些字符串是由前面的顺序写benchmark写入的。相似地,随机读benchmark会以随机的方式读取随机写benchmark所写入的数据。

        Scan benchmark和顺序读benchmark相似,可是,使用了由BigTable API所提供的支持,来扫描属于某个域区间内的全部值。使用一个scan,减小了由benchmark所执行的RPC的数量,由于,在Scan中,只须要一个RPC就能够从tablet服务器中获取大量顺序值。

        随机读(mem) benchmark和随机读benchmark相似,可是,包含这个benchmark数据的局部群组,被标记为in-memory,所以,它是从内存中读取所需数据,而不是从GFS中读取数据。对这个benchmark而言,咱们把每一个tablet服务器所包含数据的数量,从1GB减小到100MB,从而能够很好地装入tablet服务器可用内存中。

Google Bigtable,厦门大学,厦门大学计算机系,数据库实验室,林子雨

    图6显示了,当读或写1000字节的数据到BigTable中时,咱们的benchmark的性能。表格内容显示了每一个tablet服务器每秒的操做的数量。图显示了每秒的操做的总数量。

Single-tablet-server performance

        让咱们首先考虑只有一个tablet服务器的性能。随机读的性能要比其余类型的操做的性能都要差一个数量级,甚至差更多。每一个随机读操做包含了,把一个64KB的SSTable块经过网络从GFS传输到一个tablet服务器,在这个块中,只有1000字节的数据会被使用。Tablet服务器大约每秒执行1200个操做,这会致使从GFS须要读取大约75MB/s。在这个过程当中,带宽是足够的。许多具备这种访问模式的BigTable应用都把块大小设置为更小的值8KB。

        从内存读取数据的随机读会更快一些,由于,每一个1000字节读都是从tablet服务器内存当中读取,而不须要从GFS当中读取64KB的数据。

        随机和顺序写执行的性能要好于随机读,由于,每一个tablet服务器都把全部到达的写都追加到一个单独的提交日志中,而且使用分组提交,从而使获得GFS的写操做能够流水化。在随机写和顺序写之间,没有明显的性能差异。在两种情形下,全部的写都记录在同一个提交日志中。

        顺序读的性能要好于随机读,由于从GFS中获取的每64KB SSTable块,会被存储到块缓存中,它能够为后面的64个读操做服务。

       Scan操做会更快,由于,针对单个RPC,tablet服务器能够返回大量的值,所以,RPC开销就能够分摊到大量的值当中。

Scaling

当咱们在系统中把tablet服务器的数量从1增长到500的过程当中,累计吞吐量急剧增长,一般以100倍的规模。例如,随着tablet服务器增加了500倍,针对内存的随机读的性能,增加了大约300倍,之因此会发生这种状况,由于这个benchmark的性能瓶颈是单个tablet服务器的CPU。

可是,性能不会线性增加。对于多数benchmark来讲,当把tablet服务器的数量从1增长到50时,每一个服务器的吞吐量有显著的下降。这个问题,是由多服务器环境中,负载不均衡引发的,一般因为有其余进程争抢CPU资源和网络带宽。咱们的负载均衡算法努力解决这个问题,可是,没法实现完美的目标,主要缘由在于:第一,从新负载均衡有时候会被禁止,这样作能够减小tablet迁移的数量(当一个tablet迁移时,在短期内是不可用的,一般是一秒);第二,咱们的benchmark的负载是动态变化的。

随机读benchmark显示了最差的可扩展性。当服务器数量增长500倍时,累计吞吐量的增加只有100倍左右。致使这个问题的缘由在于,对于每一个1000字节的读操做,咱们都会转移一个64KB的块。这个数据转移使得咱们的GB级别的网络很快达到饱和,这样,当咱们增长机器的数量时,单个服务器的吞吐量就会很快下降。

8 Real applications

    截止到2006年8月,已经又388个非测试的BigTable簇运行在不一样的Google服务器簇里,包括总共大约24500个tablet服务器。表1显示了每一个簇中的tablet服务器的大概分布。许多簇都是用于开发目的,所以,在不少时间内都是空闲的。一组包含14个繁忙簇(包含8069个tablet服务器),每秒钟的累积负载是120万个请求。其中,到达的RPC流量是741MB/s,出去的RPC流量大约是16GB/s。表2提供了一些关于当前正在使用的表的数据。一些表存储为用户服务的数据,而其余表则存储为批处理服务的数据。在总尺寸、平均单元格尺寸、从内存服务的数据的百分比以及表模式的复杂性方面,这些表区别很大。下面,咱们将要分别描述三个产品团队如何使用BigTable。

Google Bigtable,厦门大学,厦门大学计算机系,数据库实验室,林子雨

Google Bigtable,厦门大学,厦门大学计算机系,数据库实验室,林子雨

8.1 Google Analytics

        Google Analytics是一种服务,它帮助网站管理者分析网站流量模式。它提供了汇总分析,好比,天天不一样访问者的数量,以及天天每一个URL的网页视图的数量,以及网站流量报告,好比浏览了某个网页之后发生购买行为的用户的数量。

        为了支持这项服务,网站管理员在网页中嵌入了一个小的Javascript程序。每当页面被访问时,都会触发这个Javascript程序。它把关于这个用户访问的全部相关信息都记录在Google Analytics中,好比用户标识以及被访问的网页的信息。Google Analytics分析这些数据,并提供给网站管理员访问。

        咱们简单地描述Google Analytics所使用的两个表。网站点击表(200TB)为每一个用户访问都维护了一个行。行的名称是一个元祖,它包含了网站的名称以及session被建立的时间。这个表模式保证了,访问同一个WEB站点的session都是临近的,而且以时间顺序进行存储。这个表的压缩率能够达到14%。

        汇总表(大约20TB)包含了针对每一个网站的不一样的汇总信息。这个表是从网站点击表中经过周期性地运行MapReduce做业而获得的。每一个MapReduce做业从网站点击表当中抽取最近的session信息。系统的总吞吐量,受到了GFS吞吐量的限制。这个表的压缩率在29%左右。

8.2 Google Earth

        Google提供不少服务,它支持用户访问高清晰度的卫星图片,或者经过基于浏览器的Google Maps接口,或者经过定制的客户端软件Google Earth。这些产品容许用户在地球表面进行导航。该产品支持在不一样清晰度下查看和标注地图信息。该系统采用一个表进行数据预处理,用另外一个表位用户提供数据服务。

        这个预处理管道使用一个表来存储卫星图片。在预处理过程当中,影像数据被清洗并转换成最后的服务数据。这个表包含了大约70TB的数据,所以,是从磁盘访问的。影像数据都是通过压缩的,所以,BigTable就不存在数据压缩了。

        影像表中的每行,都对应一个单个的地理片断。行被命名,以保证相邻的地理分段在存储时彼此接近。表包含了一个列家族来跟踪每一个分段的数据。这个列家族包含了大量的列,基本上为每一个原始影像建立一个列。由于,每一个分段只是从少许几个列中的影像构建获得的,所以,这个列家族很稀疏。

        这个预处理管道严重依赖于针对BigTable的MapReduce操做来转换数据。在这些MapReduce做业运行期间,整个系统的每一个服务器大约处理1MB/秒的数据。

        这个服务系统使用一个表来对存储在GFS中的数据创建索引。这个表相对比较小,大约500GB。可是,每一个数据中心每秒钟必须以很低的延迟处理成千上万个请求。于是,这个表一般被重复存放到多个tablet服务器上,而且包含了内存列家族。

8.3 Personalized Search

        Personalized search是一种服务,它记录了用户查询和点击数据,涵盖了各个方面的Google属性,好比,网页搜索、图片和新闻。用户能够浏览他们本身的访问历史,他们能够要求根据Google使用历史模式来得到个性化的搜索结果。

        Personalized search把全部的用户数据都存放在BigTable中。每一个用户都有一个独特的用户ID,并被分配了以这个用户ID为名字的行。每种类型的动做都会存储到特定的列家族中,好比,有一个列家族存储了全部的网页查询。每一个数据元素都把这个动做发生的时间做为BigTable的时间戳。Personalized search在BigTable上使用MapReduce产生用户的profile。这些用户profile用来协助生成个性化的用户搜索结果。

        Personalized Search的数据被分布到多个BigTable簇,来增长可用性,减小由距离而产生的延迟。Personalized Search最初构建了基于BigTable的客户端副本模式,从而保证全部副本的最终一致性。当前的系统使用了一个复制子系统,它是内嵌到服务器端的。

        Personalized Search存储系统的设计,容许其余分组增长新的用户信息到他们本身的列中,这个系统当前正在被许多Google属性使用,这些属性须要存储用户的配置信息和设置。在多个分组之间共享一个表,致使了列家族数量比较大。为了帮助支持共享,咱们为BigTable增长了一个简单的配额机制,从而对共享表当中某个特定应用可使用的存储空间进行限制。这种机制为每一个用户在使用本系统的不一样的产品分组之间创建了隔离。

9 Lessons

        在设计、实现、维护和支持BigTable的过程当中,咱们收获了有益的经验,而且得到了几个有意思的教训。

        咱们获得的一个教训是,大的分布式系统很发生多种错误,不只是其余分布式系统常常遇到的标准的网络分割和故障。例如,咱们已经遇到问题,他们是由如下缘由引发的:内存和网络故障、大的时钟扭曲、机器挂起、咱们所使用的其余系统(好比Chubby)中存在的故障、GFS配额当中的溢出以及计划或非计划之中的硬件维护。随着咱们得到了更多的针对这些问题的经验,咱们已经经过改变不一样的协议来解决他们。例如,咱们为RPC机制增长了checksumming。咱们经过移除一部分系统针对另外一部分系统所作的假设,也解决了一些问题。例如,咱们取消了假设一个给定的Chubby操做只返回一个固定错误集合。

        咱们得到的另外一个教训是,在很清楚地知道如何使用一个新特性以前,不要随便增长这个新特性。例如,咱们最初计划在咱们的应用API当中支持通用的事务。由于咱们不会当即用到这种功能,因此,咱们没有实现它。如今咱们有许多应用都是运行在BigTable之上,咱们就能够考察他们的应用需求,发现不少应用只须要针对单个记录的事务。当人们须要分布式事务时,最主要的用途就在于维护二级索引,咱们就考虑增长一个特定的机制来知足这种需求。在通用性方面,这种特定机制会比通用事务模型差一些,可是,它更高效,尤为是对于那些须要跨越多个行的更新而言。

        从支持BigTable运行中得到的一个比较实际的教训是,合适的系统级别的监视的重要性,即监视BigTable本身,也监视运行在BigTable上的进程。例如,咱们扩展了咱们的RPC系统,从而使得对一些RPC样本,它会详细跟踪记录针对该RPC的重要动做。这种特性已经容许咱们探测和解决许多问题,好比针对tablet数据结构的锁冲突,当执行BigTable更新时的慢写,以及当METADATA tablet不可用时,访问METADATA表发生的阻塞。说明监视比较有用的另外一个例子是,每一个BigTable簇都是在Chubby中注册的。这就容许咱们跟踪全部的簇,发现这些簇的大小,看看它们当前使用的是咱们软件的哪一个版本,以及是否存在一些预料以外的问题,好比很大的延迟。

        咱们所得到的最重要的教训就是简单设计的价值。假设咱们系统的尺寸是大约10万行非测试代码,以及这些代码会随着时间演化,咱们发现代码和设计的清晰性对于代码和系统维护具备重要的帮助。一个例子是咱们的tablet服务器成员协议。咱们的第一个协议很简单,主服务器周期性地发布租约给tablet服务器,若是tablet服务器发现租约到期就自杀。不幸的是,当存在网络问题时,这种协议极大下降了系统的可用性,而且对于主服务器的恢复时间也很敏感。咱们前后几回更改了协议的设计,直到找到一个好的协议。可是,这个比较好的协议,太复杂,而且依赖于那些不多被其余应用使用的Chubby功能。咱们发现,咱们花费了大量的时间来调试各类晦涩的案例。最后,咱们废弃了这个协议,转向采用一个比较简单的新的协议,它只依赖那些常常被使用的Chubby功能。

10 Related Work

        Boxwood项目[24]具备一些和Chubby、GFS以及BigTable重叠的组件,由于Boxwood支持分布式协议和分布式B树存储。在每一个发生重叠的领域中,Boxwood看起来彷佛针对的是Google所提供服务的低一层次的服务。Boxwood项目的目标是提供构建高层次服务的基础架构,好比文件系统或数据库,而BigTable的目标是直接支持那些须要存储数据的客户端应用。

        许多最近的计划,已经解决了在广域网内提供分布式存储和高层次服务的问题。这些计划包括,在分布式哈希表方面的工做,好比项目CAN[29]、CHORD[32]、Tapestry[37]和Pastry[30]。这些系统解决的问题,在BigTable中没有出现,好比高可用性带宽、不可信的参与者或频繁地重配置。分布式控制和理想的零错误不是BigTable的设计目标。

        就能够提供给应用开发者的分布式存储模型而言,咱们认为,分布式B树所提供的“键-值对”模型或者分布式哈希表具备很大的局限性。“键-值对”是一个有用的积木,可是,它不该该是能够提供给应用开发者的惟一的积木。咱们所能提供的模型比简单的“键-值对”更加丰富,而且支持稀疏的办结构化数据。可是,它是很是简单的,而且足以支持很是高效的平面文件表示,而且它足够透明,容许用户来调节系统重要的行为。

        有几个数据库开发商已经开发了并行数据库,它能够存储大量的数据。Oracle的Real Application Cluster数据库[27],使用共享的磁盘来存储数据(BigTable使用GFS),而且使用一个分布式的锁管理器(BigTable使用Chubby)。IBM的DB2 Parallel Edition[4]是基于非共享[33]的体系架构,这一点和BigTable相似。每一个DB2服务器负责表中行的一个子集,它被存储在一个局部关系数据库中。IBM的DB2 Parallel Edition和Oracle的Real Application Cluster都提供了完整的事务模型。

        BigTable局部分组实现了和其余一些系统相似的压缩和磁盘读性能,这些系统在磁盘上存储数据室,采用基于列而不是基于行的存储,包括C-store[1,34]和商业化产品,好比Sybase IQ[15,36],SenSage[31],KDB+[32],以及在MonetDB/X100[38]当中的ColumnBM存储层。另外一个把数据垂直和水平分区到平面文件中而且取得了很好的数据压缩率的系统是,AT&T的Daytona数据库[19]。局部分组不支持CPU缓存级别的优化,好比那些在Ailamaki[2]中描述的。

        BigTable使用memtable和SSTable来存储tablet更新的方式,和Log-Structured Merge Tree[26]用来存储索引更新的方式是相似的。在这两个系统中,排序的数据在写入到磁盘以前是存放在内存之中的,读操做必须把来自磁盘和内存的数据进行合并。

        C-Store和BigTable具备不少类似的特性:两个系统都使用非共享的体系架构,都有两个不一样的数据结构,一个是为存放最近的写操做,一个是为存放长期的数据,而且设计了把数据从一个结构转移到另外一个结构的机制。可是,这两个系统在API方面具备很大的区别:C-Store就像一个关系型的数据库,而BigTable提供了一个低层次的读和写接口,而且被设计成在每一个服务器上每秒钟内提供成千上万的这种操做。C-Store也是一个读优化的关系型DBMS,而BigTable对读敏感和写敏感的应用都提供了很好的性能。

        BigTable的负载均衡器,必须解决负载均衡和内存均衡问题,这也是非共享数据库[11,35]一般面临的问题。咱们的问题更加简单一些:(1)咱们不考虑同一个数据存在多个副本的情形,咱们可能采用视图或索引的形式以另外一种方式来看待副本;(2)咱们让用户告诉咱们,什么数据应该放在内存中,什么数据应该放在磁盘上,而不是系统本身尽力去猜想数据的存放位置;(3)咱们没有复杂的查询优化机制,也不执行复杂的查询。

11 Conclusions

        咱们已经描述了BigTable,一个为Google存储数据的分布式存系统。自从2005年4月开始,BigTable簇已经在实际生产系统中使用。在那以前,咱们已经投入了7个person-years在设计和开发上。截止2006年8月,有超过60项计划正在使用BigTable。咱们的用户喜欢BigTable 提供的高性能和高可用性。当用户的资源需求随着时间变化时,他们只须要简单地往系统中添加机器,就能够实现服务器簇的扩展。

        鉴于BigTable的不一样寻常的接口,一个有意思的问题是,咱们的用户适应BigTable的过程是多么艰难。新的用户有时候不知道如何很好地使用BigTable提供的接口,尤为是,他们已经习惯使用支持通用事务的关系型数据库。可是,许多Google产品成功地使用BigTable来存放数据这样一个事实,已经说明BigTable设计的成功。

        咱们正在考虑增长其余几个额外的BigTable功能,好比支持二级索引,以及一个基础框架,它能够支持构建跨数据中心分布BigTable数据。咱们已经开始把BigTable做为一个服务提供给产品组,从而使得每一个组都不须要维护他们本身的簇。随着咱们的服务簇的扩展,咱们须要处理更多的BigTable内部的资源共享的问题。

        

最后值得一提的是,咱们发如今google构建咱们的存储解决方案有很大的优点。咱们不只有足够的灵活度为bigtable设计数据模型,咱们还可以彻底控制BigTable的实现,甚至Bigtable依赖的其它google基础设施。这些权限意味着一旦(bigtable或其依赖的基础设施)出现了瓶颈和低效之处,咱们可以及时解决。

 

Acknowledgements

We thank the anonymous reviewers, David Nagle, and our shepherd Brad Calder, for their feedback on this paper. The Bigtable system has benefited greatly from the
feedback of our many users within Google. In addition, we thank the following people for their contributions to Bigtable: Dan Aguayo, Sameer Ajmani, Zhifeng Chen,
Bill Coughran, Mike Epstein, Healfdene Goguen, Robert Griesemer, Jeremy Hylton, Josh Hyman, Alex Khesin, Joanna Kulik, Alberto Lerner, Sherry Listgarten, Mike
Maloney, Eduardo Pinheiro, Kathy Polizzi, Frank Yellin, and Arthur Zwiegincew.(厦门大学林子雨翻译 标注:致谢就不翻译了啊)

References

[1] ABADI, D. J., MADDEN, S. R., AND FERREIRA,M. C. Integrating compression and execution in columnoriented database systems. Proc. of SIGMOD (2006).
[2] AILAMAKI, A., DEWITT, D. J., HILL, M. D., AND SKOUNAKIS, M. Weaving relations for cache performance. In The VLDB Journal (2001), pp. 169–180.
[3] BANGA, G., DRUSCHEL, P., AND MOGUL, J. C. Resource containers: A new facility for resource management in server systems. In Proc. of the 3rd OSDI (Feb.1999), pp. 45–58.
[4] BARU, C. K., FECTEAU, G., GOYAL, A., HSIAO,H., JHINGRAN, A., PADMANABHAN, S., COPELAND, G. P., AND WILSON, W. G. DB2 parallel edition. IBM Systems Journal 34, 2 (1995), 292–322.
[5] BAVIER, A., BOWMAN, M., CHUN, B., CULLER, D., KARLIN, S., PETERSON, L., ROSCOE, T., SPALINK, T.,AND WAWRZONIAK, M. Operating system support for planetary-scale network services. In Proc. of the 1st NSDI (Mar. 2004), pp. 253–266.
[6] BENTLEY, J. L., AND MCILROY, M. D. Data compression using long common strings. In Data Compression Conference (1999), pp. 287–295.
[7] BLOOM, B. H. Space/time trade-offs in hash coding with allowable errors. CACM 13, 7 (1970), 422–426.
[8] BURROWS, M. The Chubby lock service for looselycoupled distributed systems. In Proc. of the 7th OSDI (Nov. 2006).
[9] CHANDRA, T., GRIESEMER, R., AND REDSTONE, J. Paxos made live — An engineering perspective. In Proc. of PODC (2007).
[10] COMER, D. Ubiquitous B-tree. Computing Surveys 11, 2 (June 1979), 121–137.
[11] COPELAND, G. P., ALEXANDER, W., BOUGHTER, E. E., AND KELLER, T. W. Data placement in Bubba. In Proc. of SIGMOD (1988), pp. 99–108.
[12] DEAN, J., AND GHEMAWAT, S. MapReduce: Simplified data processing on large clusters. In Proc. of the 6th OSDI (Dec. 2004), pp. 137–150.
[13] DEWITT, D., KATZ, R., OLKEN, F., SHAPIRO, L., STONEBRAKER, M., AND WOOD, D. Implementation techniques for main memory database systems. In Proc. of SIGMOD (June 1984), pp. 1–8.
[14] DEWITT, D. J., AND GRAY, J. Parallel database systems: The future of high performance database systems. CACM 35, 6 (June 1992), 85–98.
[15] FRENCH, C. D. One size fits all database architectures do not work for DSS. In Proc. of SIGMOD (May 1995), pp. 449–450.
[16] GAWLICK, D., AND KINKADE, D. Varieties of concurrency control in IMS/VS fast path. Database Engineering Bulletin 8, 2 (1985), 3–10.
[17] GHEMAWAT, S., GOBIOFF, H., AND LEUNG, S.-T. The Google file system. In Proc. of the 19th ACM SOSP (Dec.2003), pp. 29–43.
[18] GRAY, J. Notes on database operating systems. In Operating Systems — An Advanced Course, vol. 60 of Lecture Notes in Computer Science. Springer-Verlag, 1978.
[19] GREER, R. Daytona and the fourth-generation language Cymbal. In Proc. of SIGMOD (1999), pp. 525–526.
[20] HAGMANN, R. Reimplementing the Cedar file system using logging and group commit. In Proc. of the 11th SOSP (Dec. 1987), pp. 155–162.
[21] HARTMAN, J. H., AND OUSTERHOUT, J. K. The Zebra striped network file system. In Proc. of the 14th SOSP (Asheville, NC, 1993), pp. 29–43.
[22] KX.COM. kx.com/products/database.php. Product page.
[23] LAMPORT, L. The part-time parliament. ACM TOCS 16,2 (1998), 133–169.
[24] MACCORMICK, J., MURPHY, N., NAJORK, M., THEKKATH, C. A., AND ZHOU, L. Boxwood: Abstractions as the foundation for storage infrastructure. In Proc. of the 6th OSDI (Dec. 2004), pp. 105–120.
[25] MCCARTHY, J. Recursive functions of symbolic expressions and their computation by machine. CACM3, 4 (Apr. 1960), 184–195.
[26] O’NEIL, P., CHENG, E., GAWLICK, D., AND O’NEIL,E. The log-structured merge-tree (LSM-tree). Acta Inf.33, 4 (1996), 351–385.
[27] ORACLE.COM. www.oracle.com/technology/products/-database/clustering/index.html. Product page.
[28] PIKE, R., DORWARD, S., GRIESEMER, R., AND QUINLAN, S. Interpreting the data: Parallel analysis with Sawzall. Scientific Programming Journal 13, 4 (2005),227–298.
[29] RATNASAMY, S., FRANCIS, P., HANDLEY, M., KARP, R., AND SHENKER, S. A scalable content-addressable network. In Proc. of SIGCOMM (Aug. 2001), pp. 161–172.
[30] ROWSTRON, A., AND DRUSCHEL, P. Pastry: Scalable, distributed object location and routing for largescale peer-to-peer systems. In Proc. of Middleware 2001 (Nov. 2001), pp. 329–350.
[31] SENSAGE.COM. sensage.com/products-sensage.htm. Product page.
[32] STOICA, I., MORRIS, R., KARGER, D., KAASHOEK, M. F., AND BALAKRISHNAN, H. Chord: A scalable peer-to-peer lookup service for Internet applications. In Proc. of SIGCOMM (Aug. 2001), pp. 149–160.
[33] STONEBRAKER, M. The case for shared nothing. Database Engineering Bulletin 9, 1 (Mar. 1986), 4–9.
[34] STONEBRAKER, M., ABADI, D. J., BATKIN, A., CHEN, X., CHERNIACK, M., FERREIRA, M., LAU, E., LIN, A., MADDEN, S., O’NEIL, E., O’NEIL, P., RASIN, A., TRAN, N., AND ZDONIK, S. C-Store: A columnoriented DBMS. In Proc. of VLDB (Aug. 2005), pp. 553–564.
[35] STONEBRAKER, M., AOKI, P. M., DEVINE, R., LITWIN, W., AND OLSON, M. A. Mariposa: A new architecture for distributed data. In Proc. of the Tenth ICDE(1994), IEEE Computer Society, pp. 54–65.
[36] SYBASE.COM. www.sybase.com/products/databaseservers/sybaseiq. Product page.
[37] ZHAO, B. Y., KUBIATOWICZ, J., AND JOSEPH, A. D. Tapestry: An infrastructure for fault-tolerant wide-area location and routing. Tech. Rep. UCB/CSD-01-1141, CS Division, UC Berkeley, Apr. 2001.
[38] ZUKOWSKI, M., BONCZ, P. A., NES, N., AND HEMAN, S. MonetDB/X100—A DBMS in the CPU cache. IEEE Data Eng. Bull. 28, 2 (2005), 17–22.

(厦门大学计算机系 林子雨 翻译)