HBase与BigTable的比较(翻译)

原文链接: http://www.spnguru.com/?p=165

这是对HBase vs. BigTable Comparison一篇翻译,网上很多blog都转载了,虽然是2009年的文章,现在看起来还是有价值的,所以这里再次转载一下。

————————————– 毫无理由的分割线 ———————————

众说周知,HBase是Google的BigTable架构的一个开源实现。但是我个人觉得,要做到充分了解下面两点还是有点困难的:

一 HBase涵盖了BigTable规范的哪些部分?
二 HBase与BigTable仍然有哪些区别?

下面我将对这两个系统做些比较。

在做比较之前,我要指出一个事实:HBase是非常接近BigTable论文描述的东西。撇开一些细微的不同,比如HBase 0.20使用ZooKeeper做它的分布式协调服务,HBase已经基本实现了BigTable所有的功能,所以我下面的篇幅重点落在它们细微的区别上,当然也可以说是HBase小组正在努力改进的地方上。

比较范围

本文比较的是基于七年前发表的论文(OSDI’06)所描叙的Google BigTable系统,该系统从2005年开始运作。就在论文发表的2006年末到2007年初,作为Hadoop的子项目的HBase也产生了。在那时,HBase的版本是0.15.0. 如今大约2年过去了,Hadoop 0.20.1和HBase 0.20.2都已发布,你当然希望有一些真正的改进。要知道我所比较的是一篇14页的技术论文和一个从头到脚都一览无余的开源项目。所以下面的比较内容里关于HBase怎么做的讲得比较多点。

在文章的结尾,我也会讨论一些BigTable的如今的新功能,以及HBase跟它们比较如何。好,我们就从术语开始。

术语

有少数几个不同的术语被两个系统用来描述同样的事物。最显著的莫过于HBase中的regions和BigTable中的tablet。自然地,它们各自把一连串的行(Rows)切分交给许多Region server或者tablet server管理。

特性比较

接下来的就是特性比较列表,列表中是BigTable跟HBase的特性比较。有的是一些实现细节,有的是可配置的选项等。让人感到有困惑的是,将这些特性分类很难。

特性

BigTable

HBase

说明

//修改的原子性

支持,每行

支持,每行

因为BigTable不像关系型数据库,所以不支持事务。最接近事务的就是让对每行数据访问具有原子性。HBase同样实现了”行锁”的API,让用户访问数据时给一行或者几行数据加锁。

词典顺序的行排序

支持

支持

所以行都按照词典顺序排序

数据块支持

支持

支持

在数据存储文件中,数据是由更小的数据块构成的。这使从大的存储文件读取数据更快。数据块的大小是可配置的,典型配置是64K

数据块压缩

支持,按Column Family

支持,按Column Family

Google使用BMDiffZippy做两步处理。BMDiff工作得很好是因为存储文件中相邻的key-value对的内容经常非常相似。因为数据支持多个版本,几个版本的内容会被排序然后被存在一起,它们之间有很多相同的内容。或者row key也会被用这样的方式处理,比如如果用URL来作为row key,而这些URL来自统一个网站,那么row key也会有很多相似之处。Zippy使用的是改进的LZW算法。HBase使用的是Java支持的标准的GZip,以及一点点GPL licensed LZO格式支持。 Hadoop也有想使用BMDiffZippy的征兆。

Column Family数量限制

最多几百

小于100

理论上行数和列数是无限的,可是列族(column family)却不是。这个只是设计上的一些折中考率.

Column Famil命名格式

可打印

可打印

HBase这样做的主要原因是Column Famil的名称会被作为文件系统中的目录名称

Qualifier命名的格式

任意

任意

任意的字节数组

Key/Value对的格式

任意

任意

任意的字节数组

访问控制

支持

BigTable支持column family级别的访问控制。HBase暂不支持

Cell 多版本

支持

支持

多版本支持是基于时间戳。

 

版本数目限制可以基于cloumn family级别自由配置

自定义时间戳

支持

支持

两个系统都支持用户设定时间戳,如果用户不指定,则使用当前时间作为时间戳。

数据TTL

支持

支持

除了数据可以有多个版本,用户还可制定TTLtime-to-live),当数据到期后会被清除

批量写入

支持

支持

都支持批量表操作

值计数器

支持

支持

两者都可使用特定的列作为原子计数器。HBase实现是:当计数器的值要增长时,它必须获得行锁。

行过滤器

支持

支持

两者都支持扫描行时支持行过滤器

客户端脚本执行

支持

不支持

BigTable使用Sawzall使客户端可以处理存储的数据。

MapReduce支持

支持

支持

两者都有方便的工具类让MapReduce Job扫描表。

底层文件系统

GFS

HDFS,S3, S3N, EBS

BigTable工作在GFS之上,HBase可以使用任何文件系统,只要有该文件系统的代理或者驱动即可。

存储文件格式

SSTable

HFile

 
块索引

在文件最后

在文件最后

两者都有相似的块结构化的存储文件格式,并且块索引被放在文件的最后

内存映射

支持

不支持

BigTable可以让存储文件直接映射到内存。

锁服务

Chubby

ZooKeeper

ZooKeeperHBase用来协调任务并非当成锁服务。总体说来,HBase使用ZooKeeper达到了BigTable使用Chubby的效果,只有语义有点细微区别。

单个Master

不是

HBase近来支持多个Master。多个Master是”热”待命模式工作,它们都侦听ZooKeeper 上的Master节点。

Tablet/Region 数目

10-1000

10-1000

两个系统都推荐每个Region server分配相同数目的region。当然这决定于很多因素,由于两个系统都使用普通电脑,出于负载考虑,它们推荐相同的数目

Tablet/Region大小

100-200MB

256MB

在两个系统中,单个Region大小是可配置的,在HBase中,默认大小为256MB

Root 位置

1st META / Chubby

-ROOT- / ZooKeeper

HBase会使用一个只有单个Region的自身表来存储Root表。二者启动时都会把Root region所在机器的地址放到ZooKeeper或者Chubby中。

客户端Region信息缓存

支持

支持

二者客户端都支持Region位置信息缓存并且有相应的机制去除过时的缓存和更新缓存

Meta 预读

支持

不支持(?)

BigTable的一个设计就是会预读超过1Meta Region信息并将之放入客户端缓存。

Region事件记录

支持

支持

Region相关事件(切分,分配,再分配)都会记录在Meta表中

存储位置分组(Locality Groups

支持

不支持

这不是很确定,但是看起来BigTable中的任何东西都有个位置分组的属相。如果多个列族的位置分组相同,那么它们将被存放在一起,并且拥有相同的配置参数。单个列族就可能是一个拥有一个成员的位置分组。HBase不支持这种选项,并将不同的列族分开存储。

完全内存Column Family存储

支持

支持

这是为需要高速存取小表准备的

KeyValue 缓存

支持

不支持

缓存热点Cell数据

数据块缓存

支持

支持

数据块从存储文件读入到在可配置的缓存中

布隆过滤器(Bloom Filters)

支持

支持

这些过滤器会消耗一些内存,但是可以快速检查一个指定的cell是否在一个Region Server上存在

Write-Ahead Log (WAL)

支持

支持

每个Region Server都会记录被它管理的所有Region上的数据改动

Secondary Log

支持

不支持

出于性能考虑,一旦WAL性能下降,BigTable还有别的log可以使用

忽略Write-Ahead Log

支持

在大量数据导入时,HBase的客户端可以选择忽略WAL

快速Region切分

支持

支持

切分region是快速的,因为切分出来的子region暂时还会去读取原存储文件直到一个compaction将数据写入region的自有的存储文件

BigTable 新特性

OSDI’06 BigTable论文发表已有几年,BigTable当然也有改进。杰夫.迪恩—一个在Google的家伙在近来的一些演讲和演示中提到了BigTable的新特性。我们就来瞧瞧部分新特性吧。

特性

BigTable

HBase

说明

客户端隔离

支持

不支持

BigTable可以内在地被用来服务很多单独的客户端,并且使它们的数据隔离不互相影响

协同处理(Coprocessors

支持

暂不支持

BigTableregion中运行的代码可以随着region的被切分,代码也被会切分到新的region上运行。

数据错误安全

支持

不支持

BigTable使用CRC校验码确认数据是否被安全写入。HBase没有这个特性,问题是:Hadoop是否会包含这个特性?

数据中心间数据复制

支持

暂不支持

HBase的一个issueHBASE-1295 就是关于这个特性的。

BigTable 新特性

OSDI’06 BigTable论文发表已有几年,BigTable当然也有改进。杰夫.迪恩—一个在Google的家伙在近来的一些演讲和演示中提到了BigTable的新特性。我们就来瞧瞧部分新特性吧。

BigTableChubby来完成一些不同的任务:保证在任何时候只有一个活动的Master;存储BigTable引导区地址;发现tablet server以及在table server死亡时做善后工作;存储BigTableschema信息(每个表的列族信息);存储访问控制列表。如果Chubby在一段较长的时候变得不可用,那么BigTable系统就会变得不可用。

变化和差异

上面讨论的一些特性比较可以看出有些特性差异并不是可以简单归结为”是或否”类的问题,对这类问题我将在下面单独探讨。

锁服务

下面的来自BigTable论文

BigTable用Chubby来完成一些不同的任务:保证在任何时候只有一个活动的Master;存储BigTable引导区地址;发现tablet server以及在table server死亡时做善后工作;存储BigTable的schema信息(每个表的列族信息);存储访问控制列表。如果Chubby在一段较长的时候变得不可用,那么BigTable系统就会变得不可用。

BigTable如何使用Chubby跟HBase如何使用ZooKeeper有很多异曲同工之处。但有一个区别就是:HBase并不把Schema信息存储在ZooKeeper中。它们都非常依赖锁服务的正常运作。根据我自身的经验以及我阅读HBase邮件列表所得到的,我们经常低估当ZooKeeper无法取得足够的资源去作出实时回应时的后果。宁可让ZooKeeper集群运行在相对较老旧的但是什么别的事都不干的机器上,而不是运行在已被Hadoop或者HBase进程搞得不堪重负的机器上。一旦你的ZooKeeper没有足够的资源提供服务,就会引发多米诺骨式的效应,HBase将会挂掉—包括master节点。

更新:在跟ZooKeeper开发小组讨论后,我想指出的是这并不真正意义上是ZooKeeper的一个问题。因为如果运行ZooKeeper的机器负荷很重,那么存取ZooKeeper上的资源很可能会超时。在这种情形下,HBase的Region Server甚至Master可能会认为协调服务已经坏了,它们就会让自己停工关闭。 帕特里克.亨特已经通过邮件和发帖对此作出回应。你可以读他的邮件或者帖子,然后检查自己的ZooKeeper是否有能力处理负荷。我个人建议是将ZooKeeper集群跟HBase集群分开。你可以把ZooKeeper集群运行在一组空闲的稍微有点过时但是性能还相当不错的机器上。这样你可以单独监控ZooKeeper集群和HBase集群中的机器,而不必有以下的烦恼:当一个机器的CPU负荷100%的时候,你搞不清楚这个负荷究竟来自哪个进程或者有什么后果。

另外一个重要区别是:ZooKeeper并不是一个像Chubby一样的锁服务系统,但是目前为止,这并不是HBase所关心的。ZooKeeer提供一个分布式的协调服务,让HBase可以选举出Master节点。它也可以提供用以表示状态或者某个动作需要的信号量。当Chubby生成一个锁文件来表示一个tablet活动的,与此相对应的一个Region server会在ZooKeeper中生成一个节点来表示自己的存在。这个节点创建以后,只要ZooKeeper不挂,它会一直存在。在BigTable中,当一个tablet server的锁文件被删除时就表示与这个tablet server的租约失效。在HBase中,因为ZooKeeper相对少点限制的架构,这种行为会被处理得有所不同。它们只是语义上有所差别,并不意味着谁优谁劣,仅仅有所不同而已。

在Chubby中,第一层级的文件包含着根tablet的位置信息。根tablet包含着一个特别的名叫METADATA(元数据)表的所有的tablet的位置信息。每个METADATA的tablet包含着一组用户表的tablet的位置信息。根tablet仅仅是METADATA表中第一个tablet,但是它被特别的看待—它从不会被切分,这是为了保证tablet的位置层级不会超过3层。

就如上面所说的,在HBase中,根region是一个只有单个region的表。要说有什么区别的话,那就是根region并不是meta表中的第一个不可切分的region。它们是相同的功能,只是实现上有差别。

METADATA表存储着tablet的位置信息,跟在起始row key和末尾row key以及表名之后。

HBase的做法有点不同,它也会为每个region存储起始的row key和末尾row key,但是末尾的row key并不是属于当前的region的,它会是另一个region的起始row key.

Master的行为

为了侦测一个tablet server是否不再为它的tablets服务,master会定期地查看每个tablet server锁文件的状态。当一个tablet server报告它丢失了锁文件,或者master经过几次尝试后未能联系上tablet server, master就会尝试在tablet server的锁文件上获得独占锁。如果master可以获得这个锁,还有Chubby是良好工作的,这时如果tablet server已经死亡或者已经把错误上报给Chubby,这时master就可以确定该tablet server不可能恢复,于是会删除它的锁文件。一旦一个tablet server的锁文件被删除,本来被该tablet server服务的tablets会被移到没被分配的tablets集合中去。为了保证master和Chubby之间网络畅通,只要master的Chubby session过期,master将会自杀。

直到0.20.2版本,HBase的行为都相当不同。Region server利用heartbeat协议给master定期报告,master接到报告就知道region server还活着。

Master启动

Master启动有以下步骤:(1)Master从Chubby中获取唯一的master锁,用来防止多个master的初始化(2)Master 扫描Chubby中的server目录找到活动的server.(3) Master跟多个活动的tablet server通讯,收集tablets的分配情况(4)Master扫描METADATA表得知所有的tablets集合。(4)Master如果发现有tablet并没有分配到tablet server,它会将之放入未被分配tablets集合,这样这个tablet就会被认为是可以被分配的。

就如我上面提到的,HBase实际上会等待所有的region server上报它负责的region情况。当然,它也会扫描.META. 表去了解有哪些region以及它们是分配到哪些region server上了。

ZooKeeper仅仅用来发布-ROOT- region所在的region server的地址。

Tablet/Region切分

在切分通知被丢失时(因为tablet server挂了或者master挂了)的情况下,当master要求tablet server装载被切分的那个tablet时,master会发现新的tablet. Tablet server会将此次切分通知master,因为它会发现在METADATA中找到的tablet只是master要求它装载的tablet的一部分。

Master节点会单独利用.META.表去发现一个region去切分,但是切分事件消息被丢失的情况。Master会按往常一样扫描.META.去发现,哪些region并没有被分配。一旦发现没有被分配的region,master会用默认的策略将之分配到一个region server上。

压紧(Compaction)

随着写动作的执行,内存表的大小会不断增长。当内存表的容量到达一个临界点时,内存表将被冻结,一个新的内存表将会被创建,被冻结的内存表将被会转换成SSTable并被写入到GFS中。这种minor compaction操作有2个目的:1降低tablet server的内存用量,2当一个tablet server死而复生从commit log读取数据时,减少数据总量。当压紧动作发生时,认可继续执行读写操作。

HBase也有相应的操作,不过被命名为”flush”。对应BigTable的”minor compaction”,HBase会把最近生成的很多较小的存储文件重写为一个包含较多数据的大文件。

…我们将限制此类文件的数目,方式是定期地在后台执行合并压紧操作。合并压紧操作就是读取几个SSTable和内存表的内容,然后写到一个新的SSTable中去。一旦合并压紧操作完成,老的SSTable和内存表就将可被丢弃。

这个动作跟HBase中的”小压紧”差不多。

读取所有的SSTable,重新写成一个SSTable的合并压紧操作被称为是major compaction

相应的在HBase中,一个major compaction就是把所有的存储文件重写成一个新的文件。

文件不可修改

要知道文件一旦被写入将不能修改,BigTable有如下的假定:

唯一可以被修改的数据结构就是读写都可以的内存表(memtable)。为了避免同时读写内存表的冲突,我们在写内存表的数据行的时候,会先复制一个副本,这样读写就可以并行处理了。

我相信HBase中的做法跟此类似,但不是很确定。可以确定是,根据HDFS的架构,文件一旦被写入就是不能被修改的。

我唯一的建议就是你自己去阅读BigTable的相关资料以形成自己的见解。这篇帖子的灵感来自一个念头:BigTable究竟实现了哪些特性,HBase涵盖了BigTable的哪些特性?写这片帖子的困难毫无疑问是我们对BigTable的细节所知不多。但是关于它的论文数量–即便是2006年的论文列表都给人留下难以磨灭的印象。HBase作为一个开源项目,而且项目的贡献者是为数不多的有着全职工作的人,现在虽不能说跟BigTable相提并论,但怎么说都我都认为现在的成果是一个巨大的成就。看看0.21和0.22的路线图,将来它们之间不大的差距将会变得更加缩小。


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值