Apache HBase Region Splitting and Merging

本文翻译于

这篇文章我们深入的理解HBase的核心区域之一。我们会特别的关注一下HBase是怎样分布负载和管理splitting的。HBase在一个table里面存储很多行的数据,table被分裂成很多称之为"Region"的块。这些Region被分布在集群里,RegionServer进程会管理这些Region,让它们可以被客户端进程访问到。一个Region存储的是连续的行,一个Region里面的行是从start key到end key进行排序的。Regions是不重叠的,这意味着同一时刻同一行的数据只能存在与一个Region中,一个Region也只能存在与一个RegionServer中,这是HBase保持强一致性的关键。和-ROOT-、.META.表一起,一个table的region可以在三次B-TREE的寻址中被定位到。

反过来,Region是由很多Store组成的,每个store对应着一个列族(columns family)的数据,一个stroe又包含着一个memstore和0~多个stroefile,每个列族的数据就是这样单独分开的。

一个table由很多region组成,这些region被很多regionserver托管着。region用这种物理的机制将读写的负载分布到各个regionserver中去。当一个table首次被创建的时候,HBase默认会只分配一个Region给这个table,这意味着初始状态下,不管regionserver的数量是多少,所有对这张表的请求都会到一个Regionserver中去。这是初始阶段将数据加载到空表不能利用整个集群的容量的主要原因。

HBase初始table的时候只创建一个Region的原因是因为它不知道在row key的范围内怎么去创建一个分裂点(split point),做这样的决策是基于你的数据里面key分布的很开。而不是随便猜测一个分裂点而让你来处理最后的后果,HBase提供了从客户端来进行管理的工具。通过一个叫pre-splitting的进程,你可以通过提供splitting key来创建一个初始状态下就拥有多个Region的table。pre-splitting可以让初始table的时候读写负载可以始终分布到集群上,但是你要考虑到你是否事先知道table的key的分布。并且pre-splitting也是有风险的,有时候会因为数据的倾斜和数据量非常大的row使负载并不能合理分布到集群中。如果初始的splitting point没有选择好,你会面临的将是复杂的负载分布,这会限制你集群的性能。

有一个问题就是如何计算pre-splitting的split point,你可以是用RegionSplitter 这个类,RegionSplitter 使用SplitAlgorithm 算法,HexStringSplit和UniformSplit是两个预定义的算法,前者可以用于row key 拥有前缀或者十六进制字符串的情况(比如你使用了hash值当做前缀)。

Auto Splitting

不管是否使用了pre-splitting,一旦region的大小达到了一定的限制,它就会自动分裂成两个region。如果你使用的是HBase 0.9.4之前的版本,你可以通过配置RegionSplitPolicy来决定HBase何时分裂一个Region,以及如何计算split point,这里有一些预定义的split策略: ConstantSizeRegionSplitPolicy ,IncreasingToUpperBoundRegionSplitPolicy和。

ConstantSizeRegionSplitPolicy是HBase0.94默认并且唯一的split policy,当region中的某一个store的大小超过了配置中的参数时(hbase.hregion.max.filesize,默认值为10G),region就会自动分裂。

0.94版本的HBase的默认分裂策略是IncreasingToUpperBoundRegionSplitPolicy,它根据在同一个RegionServer上面的region数量作出更加激进的分裂。这种分裂策略的最大store size是根据Min (R^2 * “hbase.hregion.memstore.flush.size”, “hbase.hregion.max.filesize”)确定的,R是同一张表中在同一个RegionServer中的Region数量确定的。举个例子,默认memstore flush size 为128M,默认max store size是10G,regionserver上的第一个region分裂会在第一次memstore达到128M的时候,当regionserver上面的region数量增多,split size就会增加,512M,1152M,2G,3.2G,4.6G,6.2G,当达到9个region的时候,split size就会超过配置的max store size 10G,10G就会作为split size。

Forced Splits

HBase同样允许客户端强制分裂在线的table,比如,HBase Shell 可以用来split一个表所有的region,并且提供split point。

hbase(main):024:0> split ‘b07d0034cbe72cb040ae9cf66300a10c’, ‘b’0 row(s) in 0.1620 seconds

Split是怎么实现的

当regionServer处理写请求的时候,数据在memstore里面堆积,当memstore满的时候,它的内容会被作为stroe file写入到磁盘中去。这个事件叫做”memstore flush“。当store file 堆积得过多的时候,RegionServer会执行compact将它们合并成大文件。当flush或者compact完成之后,,RegionSplitPolicy会决定region是否要分裂成两个region。当分裂发生的时候,新创建的子Region不会将数据写入到新的文件中,取而代之的是创建被两个称之为 Reference的链接文件,分别指向分裂之后的上下两部分,链接文件会被当做常规的数据文件使用,但是只能使用原region的上或者下部分。region只有在没有连接文件指向他的时候才能分裂,这些连接文件会在compaction发生的时候被清除,这时候子Region才真正把数据写入到自己的数据结构中,消除了到父Region的链接。

尽管split region是region server所做的决定,但是split 进程必须和组件协调进行。RegionServer会在分裂前后通知Master,更新.META.表使客户端可以发现新的region,改变region在HDFS的目录、结构和数据文件。分裂是一个多任务的进程。为了能够在发生错误的时候进行回滚,RegionServer将分裂执行的状态保存在内存的日志中。下面的图中Mater和RegionServer执行的步骤用红色标出,客户端则用绿色。

1.RegionServer决定要分裂Region,并且开始准备分裂,第一步,在zookeeper上创建一个znode ,/hbase/region-in-transition/region-name,状态置为SPLITTING。

2.由于Master 订阅了/hbase/region-in-transition/ 这个znode,所以Master能收到这个目录变更的通知。

3.RegionServer在父Region的HDFS目录下创建 .split目录

一个人,一条路,人在途中,心随景动,

Apache HBase Region Splitting and Merging

相关文章:

你感兴趣的文章:

标签云: