hbase split

Region Split

Region大小超过阀值(可以是hbase.hregion.max.filesize也可以是建表时列族配置的大小)后会触发Split,由RegionServer负责来拆分region并且offline下线该region。随后将两个子region添加到hbase:meta并在RegionServer上打开后汇报给HMaster。默认情况下Region会自动触发split,同时也可以手动运行split命令。
Region Split可以手动split也可以自动split(建议),其中手动split region往往是在region出现热点时或者自动负载不均衡时通过手动split后move region来更好进行负载均衡。怎么进行Region呢?初步印象可以理解为折半拆分,每个子region是父region(原region)的一半。如图:

 

Region Split相关的参数如下:

配置参数

默认值

  

hbase.hregion.max.filesize

hbase.hregion.max.filesize10737418240 (10GB)

hbase.regionserver.region.plit.policy

IncreasingToUpperBoundRegionSplitPolicy(0.94版本后)

hbase.regionserver.regionSplitLimit

1000

hbase.client.keyvalue.maxsize

10485760 (10MB)

Qunar HBase配置

 

hbase.regionserver.region.split.policy为org.apache.hadoop.hbase.regionserver.ConstantSizeRegionSplitPolicy hbase.hregion.max.filesize为100G,为了避免拆分IO风暴。 hbase.hstore.blockingStoreFiles为30。 hbase.regionserver.regionSplitLimit配置用来限制region的数量,默认值是1000个region。

Region Split策略

HBase region split的策略由参数hbase.regionserver.region.split.policy配置。

0.94之前默认拆分策略是org.apache.hadoop.hbase.regionserver. ConstantSizeRegionSplitPolicy,该策略是基于Region配置的最大大小,由参数hbase.hregion.max.filesize指定。当Region的StoreFiles大小之和超过了hbase.hregion.max.filesize设置时,Region将被拆分。默认值是10GB。

自0.94版本后,默认策略是org.apache.hadoop.hbase.regionserver. IncreasingToUpperBoundRegionSplitPolicy,该策略是基于RegionServer上表中region个数的平方乘以memstore size 得出split region的大小,每次split的region大小并不相同,具体算法:
regionsize = Min (R^2 * “MEMSTORE_FLUSHSIZE”||”hbase.hregion.memstore.flush.size”,”hbase.hregion.max.filesize”),最大为hbase.hregion.max.filesize。
其中R为region所在regionserver上该table的region数。MEMSTORE_FLUSHSIZE为建表是DDL定义的大小,如果没有指定则使用hbase.hregion.memstore.flush.size 。
默认hbase-site文件配置hbase.hregion.memstore.flush.size 设定大小为128M,hbase.hregion.max.filesize设定大小为10G。

 

举例:表定义没有指定MEMSTORE_FLUSHSIZE,hbase.hregion.memstore.flush.size默认128M,hbase.hregion.max.filesize默认10G。 那么第一个region 是memstore刷盘到HFile的大小,即  1*1*128M=128M,生成一个region。 (1*1是region个数的平方) 当region数达到2个时,2*2*128M=512M。 (2*2是region个数的平方) 当region数达到3个时,3*3*128M=1152M。 (3*3是region个数的平方) ...依此类推... 当region数达到9个时,9*9*128M= 10368M > 10G。从第10个region开始每个region最大大小为10G(hbase.hregion.max.filesize)

同时还有一种策略是KeyPrefixRegionSplitPolicy,通过rowkey前缀位数来划分region,策略适合固定前缀的rowkey。
Qunar方便运维和管理统一使用的ConstantSizeRegionSplitPolicy(什么时候触发region split一目了然)。

Region Split流程

Region Split的流程如下:

 

1.客户端向RegionServer发送写入请求。 2.数据写入到内存memstore。 3.当memstore被填满并达到阀值,存储在内存中的数据被写入到磁盘生成HFiles,过程叫做memstore flush。 4.随着HFiles的增加,regionserver通过compact来将文件压缩成较大的文件。 5.region的数据量增加。 6.RegionServer根据region split的策略确定所属的region是否应该进行region split。 7.如果需要进行region split,则将region split请求加入到队列中(split_queue)

但是一个region实际是如何进行split呢? 是否会在某一个row key上进行split? split region会做什么?会发生什么?
RegionServer是通过如下流程进行region拆分:

 

1.当RegionServer确定需要对某个region进行拆分操作时,它将启动一个拆分事务。RegionServer首先会在表上获取一个共享锁 来防止拆分期间的schema修改。之后会在ZooKeeper中 /hbase/region-in-transition/region-name节点下创建一个znode,并将 znode状态设置为SPLITTING。 HMaster监视znode /hbase/region-in-transition时发现region(父region)需要开始拆分。

2.RegionServer在HDFS的region目录中创建一个名为.splits子目录,关闭父region并下线要拆分的父Region(本地数据结构标记 为下线)。客户端发送到给拆分region的请求都会获取到NotServingRegionException异常触发重试,该Region(父region)不再接受任何请求。

3.RegionServer在 .splits目录下(多线程并行)创建两个子region目录并创建必要的数据结构。

4.RegionServer创建两个引用文件并且引用文件指向父region的文件。

5.RegionServer在HDFS中真正创建子region目录(后续online),并将引用文件传送到相应的子region目录。

6.RegionServer向hbase:meta表发送put请求,将新建的两个子region和rowkey范围写入meta表并将父region标记为offline。在信息 没有加入到meta表之前,Client能查找到的只是父region,并不会查到新建的两个子region,同时子region在zk中的状态为SPLITTING_NEW。 如果数据写入hbase:meta成功,则region已经有效的完成拆分。如果RegionServer在单次RPC成功完成之前返回失败,则Master和 下一个RegionServer会重新打开该父region将清除有关该region拆分的脏状态和数据。如果hbase:meta更新成功完成,HBase则继续 region split的流程。如果拆分失败,则父region状态从SPLITTING变为OPEN,并且两个子region的状态从SPLITTING_NEW变为OFFLINE。

7.RegionServer并行的打开两个子region。

8.RegionServer将新region添加到hbase:meta并online。

9.之后客户端的相关请求会定向到新region并发送请求,客户端hbase:meta历史缓存被清除(因为父region已经下线,缓存非最新数据) 并从hbase:meta获取新region的信息并缓存。

10.RegionServer更新zk中znode /hbase/region-in-transition/region-name为split状态,新region的状态从SPLITTING_NEW为OPEN。 HMaster从znode发现更新,如果此时需要进行负载均衡,Hmaster会将两个子region重新分配给其它regionserver。整个region split过程完成。 对hbase中父reigon的引用会在hbase:meta和HDFS中通过compact来删除。删除过程中HMaster会定期检查子region是否还有引用指向 父region,如果没有指向,则将父region删除。

Tips:region split需要获取表锁,拆分过程中所有步骤依赖于zk,通过znode的状态进行跟踪,保证当split过程中出现问题时其它的进程能直到region的状态。

Compact

HBase合并一直是运维过程中的重点,这里打算简单说下。后续有时间整理单独的文章进行细节性总结,不是懒,是因为太多了(手动捂脸)。

HBase的写入流程是优先写WAL来实现数据不丢失,然后数据写入内存中的memstore,当memstore中数据达到给定的阀值后触发刷盘生成HFile。通过滚动memstore将数据移出内存同时丢弃对应的提交日志,内存中只保存数据为持久化道磁盘的日志。(滚动memstore是空的新memstore获取数据写入,满的memstore转存为HFile文件后移除内存)。

HBase的写入流程随着memstore中的数据不断刷写到磁盘,产生的HFile文件越来越多,HBase采用合并的方式来解决该问题。合并是指将多个文件合并成一个较大的文件。合并类型有:小合并 minor compaction 和大合并 major compaction。

小合并(minor compaction)是将多个小文件重写为数量较少的大文件,减少存储文件的数量。算法是多路合并,因为HFile文件本身是有序(memstore刷hfile前会在内存排序)的并经过归类的,所以合并速度很快,取决于磁盘IO的能力。设置minor合并处理最小文件数量由参数hbase.hstore.compaction.min设置,默认值是3。该属性最小值需要大于或等于2,过大的数字将会延迟minor合并的执行,同时也会增加执行时消耗的资源和执行时间。设置minor合并处理最大文件数量由参数hbase.hstore.compaction.max设置,默认值是10。设置合并文件大小限制是由参数hbase.hstore.compaction.max.size设置,默认值是Long.Max_VALUE,任何大于该参数值的HFile都不会参与合并。
大合并(major compaction)是将一个region中一个列族的若干个HFile重写为一个新HFile,major合并负责把所有文件压缩成一个单独的文件,在执行压缩检查时,系统自动决定运行哪种合并。

大合并和小合并不同的是:大合并能扫描所有的键值对,顺序重写全部的数据,重写数据的过程会跳过删除标记的数据,对于那些超过版本号限制和生存时间到期的数据,在重写数据时同样不会重写入新HFile。
合并和拆分在运维过程中需要考虑IO风暴的问题,避免磁盘IO压力。原因是如果HBase region按照预定的速度进行增长,触发region split的时间可能在同一时间进行,region split本身会有IO开销,当同时进行major compact时则会引起IO风暴,因此运维过程中建议手动进行split和手动进行compact。手动split的方法是将hbase.hregion.max.filesize值设置得很大(例如100G,不会经常或触发不了split),手动compact则是设置参数hbase.hregion.majorcompaction为0,凌晨通过cron定时运行大合并。

通过手动管理split和major compact能避免操作在不同的region上错开执行,避免IO集中,降低IO负载来避免拆分/合并风暴。

注意目前hbase flush和compaction操作是针对一个Region。其中Compaction操作是根据一个列族下的全部文件的数量触发的,而不是根据文件大小触发的。当一个列族操作大量数据的时候会引发一个flush,如果有多个列族则会将那些不相关的列族也进行flush操作。当很多的列族在flush和compaction时,会造成很多没用的I/O负载,要想解决这个问题需要将flush和compaction操作只针对一个列族,即创建表时指定一个列族 。

针对IO瓶颈可以适当考虑使用SSD作为存储,例如我们某个业务的统计分析集群就是使用Shannon SSD进行加速满足性能需求。综合考虑业务场景(例如历史订单和实时推荐系统)和成本,HBase可以考虑使用SSD进行性能加速,HBase自身由于数据读取多种路径(优先在memstore读取最新写入数据其次在blockcache读取缓存数据最后从磁盘HFile文件加载到内存读取数据),同时原生HBase不支持二级索引导致要么通过rowkey查询要么全表扫描,查询性能通常比RDBMS差一些(当然HBase读延时也有很多优化手段,有时间可以总结),如果将热点数据能够全部加载到block cache(RAM/SSD)或者通过SSD加速HFile读取,HBase读写性能将大大提升,另外BucketCache file模式同样是建议使用SSD存储加速性能。官方同样对SSD做了相关的优化,详情见 。

HBase hbck

hbck是HBase的管理用具,用于检查或修复HBase,当HBase集群中出现不一致的地方时hbck会格式化输出。hbck经常用于检查region一致性和表完整性。hbck工具运行会扫描整个.META表来收集表相关信息,会访问所有RegionServer以及读取所有table region里的regioninfo,所以hbck操作很重并且需要获取表锁。  同时运维过程中需要知道hbck 报告有可能是暂时的,例如region split或某个时间不可用时hbck也会打印这些不一致信息。可以加上-details参数获取详细信息并多次运行hbck确定问题是否是暂时的。
常用例子

 

修复region一致性:hbase hbck -fixAssignments

修复region在HDFS和META信息不一致: hbase hbck -fixAssignments -fixMeta

修复 region空洞或起止rowkey重叠问题: hbase hbck -repairHoles 或 hbase hbck -repair

META没有被分配,则将其正确分配: hbase hbck -fixMetaOnly -fixAssignments

META表损坏: hbase org.apache.hadoop.hbase.util.hbck.OfflineMetaRepair

离线父region发生split: hbase hbck -fixSplitParents

HBase版本文件丢失: hbase hbck -fixVersionFile

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值