关于HBase Region Overlap问题自动修复的研究

2022-06-18 02:27丛储俊张伟
新型工业化 2022年3期
关键词:故障过程

丛储俊,张伟

(上海威士顿信息技术股份有限公司,上海 200052)

0 引言

Hadoop集群以其开源、廉价、易拓展、社区资源丰富等特点,近年来成为大数据存储与分析方面最受欢迎的平台。不论是传统行业、金融业还是互联网行业都青睐于将传统数据仓库迁移至Hadoop的分布式存储系统中。

HBase是一个基于Java、开源、NoSQL、非关系型、面向列的、构建于Hadoop分布式文件系统( HDFS )上的、仿照谷歌的BigTable的论文开发的分布式数据库。

HBase是要建立一个可容错并托管一些大的数据稀疏表(亿元/兆行数以百万计列 )的应用,同时允许非常低的延迟和近实时的随机读取和随机写入。

HBase的设计保证了“以一致性为前提的可用性”,并且由于能够快速自动完成故障转移,因此也具有高可用性。

HBase将数据存储在表(table)中,一个HBase表由一个或者多个列簇(CF,column family)组成,一个列簇又包含很多列(称为列限定符,简称“CQ”,column qualifier ),每列存储相应的值。一行由很多列组成,全部由相同的行键(rowkey)引用。一个特定的列和一个行键称为单元格(cell)。一个单元格可以有很多版本,由不同时间戳的版本来区分。HBase会根据字节值将行键进行排序[1]。

物理上,一个表由一个或者多个region组成,一个region由一个或者多个列簇组成,一个列簇由一个store组成,一个store由唯一的MemStore(HBase 2.x以后支持多个MemStore)加上一个或者多个HFile组成,HFile又是由 block组成的,而block是由cell组成的。

所有的行以及相关的列一起形成了一张表。但是,为了提供可扩展以及快速随机访问的功能,HBase不得不将数据分布在多个服务器中。为了达到这个目的,表被分割成多个region存储,每个region将会存储一个指定区间的数据。region将会被分配到Region Server上,Region Server提供对于每个region的内容访问服务。当新的region被创建后,过了配置的一段时间后,HBase的负载平衡器将会把region移动到其他的Region Server上,以确保HBase集群负载均衡。

每个region都有一个起始键和一个结束键来定义它的边界,称之为rowkey范围。所有这些信息将随着文件保存在region中,也会保存在hbase:meta表中(对于HBase 0.96之前的版本则保存在 .META. 中)。通过这张表能够跟踪所有的 region信息。当region变得太大后,region可以自动分裂或者手动。如果需要,region也可以合并[2]。

正常情况下,一张表的任意两个region的起始键和结束键的范围是彼此不重叠的,这样的region可以提供正确的读写服务,如果由于某些原因导致有重叠的(overlap)region出现,则受影响范围内的行键对应的数据是不能够读写的。

本文就HBase Region Overlap的相关问题进行分析,并提出一种通过代码进行修复的方式。

1 HBase Region Overlap分析

1.1 HBase的读写流程

HBase的读写流程比较复杂,有很长的调用链,本文只对可能导致region overlap问题出现的步骤以及受region overlap问题影响的步骤进行分析。

HBase写入流程可以概括为三个阶段。

(1)客户端处理阶段:客户端将用户的写入请求进行预处理,并根据集群元数据定位即将写入数据的region所在的RegionServer,然后将请求发送给对应的RegionServer。

(2)Region写入阶段:Region Server接收到写入请求之后将数据解析出来,首先写入WAL(Write-Ahead Log,HBase的实现是HLog),再写入对应Region列簇的Mem Store。

(3)M em Stor e Fl u sh阶段:当Region中Mem Stor e容量超过一定阈值时,系统会异步执行f lush操作,将内存中的数据写入文件,形成HFile。

在HBase写入过程中,会首先从Zookeeper那里获得元数据hbase:meta表所在的Region Server,通过查询hbase:meta表获得所写数据表的region的row key范围定义以及每个region所在的region server,然后根据代写的每一条记录的row key和对应的region server联系并写入数据。如果region的row key范围发生重叠,也就是发生了region overlap问题,则一条记录可能会对应一个以上的region,无法确定应该写入哪个region,就导致了数据写入失败[3]。

HBase的读取流程更加复杂,分为get和scan两大类,这里只描述根据rowkey获得数据的get方式,这种方式受region overlap 问题的影响比较大。读取数据的时候,首先会从ZooKeeper中获取元数据hbase:meta表所在的Region Server,然后获得待读取数据表的region的元数据,包括各个region的row key范围以及所在的Region Server,最后根据row key将读取请求发送到对应的Region Server进行处理。和写入数据类似,如果region的row key范围发生了重叠,也就是发生了region overlap问题,就无法确定应该和哪个RegionServer联系,就导致了数据读取失败。

1.2 HBase的region分裂和合并流程

Region分裂是H Base最核心的功能之一,是H Base实现分布式可扩展性的基础,类似传统的My SQL的分库分表,只不过这一过程是自动的而且分裂的依据固定为row key。概括来说,当数据表的一个region的一个列簇的大小超过一定的阈值就会发生水平分裂,分裂为两个region。假设原region的row key范围为[start,end),则分裂后的两个region的范围分别为[start1,end1)和[start2,end2),其中start1=start,end2=end,end1=start2。

Region分裂有多种触发策略可以配置,一旦触发,HBase会自动寻找分裂点,就是end 1和start2,然后执行真正的分裂操作。目前HBase有多重分裂触发策略,这些策略与region overlap问题关系不大,所以这里不详细分析了。

HBase将r egion的分裂过程设计为一个完整的事务,希望整个分裂过程分为三个阶段:准备(prepare)、执行(execute)和回滚(rollback)。

Region分裂是个比较复杂的过程,涉及父Region中HFile文件分裂、两个子Region生成、系统meta元数据更改等很多子步骤,因此必须保证整个分裂过程的原子性,即要么分裂成功,要么分裂失败,在任何情况下不能出现分裂完成一半的情况。

正常的分裂结果如图1所示

不正常的分裂结果如图2所示

2 可能导致Region Overlap的原因

HBase是一个健壮的分布式系统,但是在实际生产过程中由于硬件故障、操作系统故障等原因,偶尔还是会出现莫名的崩溃,导致hbase:meta报告两个不同的region却有相同的或者重合的start key和end key。还有一种情况是运维人员或者某些工具软件跳过HBase直接操作HBase保存在HDFS上的文件或者目录,导致HBase的数据和元数据不匹配。还有一种典型的场景是在HBase 2.0上使用了hbase hbck进行强行修复,这也可能导致region overlap问题。在HBase 2.0之前,hbck提供了修复overlap的功能,但是在HBase 2.0之后,由于采用了新的分布式事务框架Procedure V2(HBASE-12439),原有的修复逻辑不能使用,而符合Procedure V2的修复功能目前还没有完成,所以强行使用hbck修复,结果是不可预期的[4]。

3 HBase Region Overlap修复方法

可以通过region的合并功能将有overlap问题的相邻的两个region进行合并,产生一个较大的region,这个region包含了原有的两个region的所有数据。

当只有少数的region overlap时,可以通过hbase shell进行手工合并,但是实际上由于硬件故障、操作系统故障、不小心的底层操作(比如直接操作HDFS文件)等原因,可能会出现大量的region overlap,这时候采用手工合并将耗费大量时间而且容易出错,所以需要基于这一思路采用编程的方式自动地实现这一合并过程。

3.1 重现问题

为了方便测试,首先需要一个能够比较快速重现region over问题的方式,这个可以通过shell脚本来实现。

空表的重现步骤是:

(1)创建一个预分区的表,比如create 't1','cf1', { NUMREGIONS => 100, SPLITALGO => 'HexStringSplit' },这会在HDFS上建立对应的目录结构。

(2)在HDFS上建立一个临时目录,然后把上述步骤建立的HBase表在HDFS上的全部内容移动到这个临时目录。

(3)Disable删除刚刚创建的HBase表,然后以同样的名字创建预分区表,但是分区的数量与第一次不同,比如create 't3','cf1', { NUMREGIONS => 70, SPLITALGO => 'HexStringSplit' }

(4)把之前临时目录的内容移动到新建表的目录下。

(5)运行hbase hbck,会报告有region目录信息存在于HDFS,但是没有存在于hbase:meta,这是预期的结果。

(6)通过hbck2 的addFsRegionsMissingInMeta功能将HDFS上的region信息写入hbase:meta。

(7)再次运行hbase hbck,会报告大量的region overlap问题。

进一步测试需要有大量数据的场景,重现步骤跟无数据的过程类似,只是建表的语句用hbase ltt -write代替,比如hbase ltt -write 30:20:10 -num_keys 10000 -num_regions_per_server 3建表后会在每个RegionServer上创建3个分区,然后用10个线程写入10000条记录,每条记录30列,每个cell的大小是20个字节,这样的场景更接近于真实环境。

3.2 编码实现查错

region的信息保存在hbase:meta表中,可以通过org.apache.hadoop.hbase.client.Admin接口的getRegions获得一个列表,这个列表是按rowkey字典顺序排序的,通过两两比较相邻的region的start和end来判断是否发生了overlap。

假设相邻的region的rowkey范围分别是[startKey1,endKey1)和[startKey2,endKey2),则有如下几种overlap的情况:RegionInfo>> regionInfos。

3.3 编码实现修复

总的思路是将查找到的有问题的每对region进行合并。两个region合并会产生第三个region,同时原有的两个region会被下线并从hbase:meta中删除,然后将新生成的region上线,整个过程是个异步过程,所以发出合并指令到最终完成需要一定的时间,这期间新的region即使和后面的region还是有overlap,也不能进行合并,强行进行合并会导致报错,所以需要加以判断,这个判断可以通过查询hbase:meta表获得必要的信息,通过查询列簇HConstants.CATALOG_FAMILY里名为“merge”的一列可以获得必要的数据。具体实现可以参考hbase-operator-tools的子项目Apache HBase HBCK2 Tool中的HBCKMetaTableAccessor代码[5]。

当HBase在拆分或者合并的时候,为了确保数据不丢失,都会保留原来的region,在拆分或者合并过程结束后再等待目录管理器来清理这些旧的region信息。在反复合并的过程中较短时间内会有大量的旧的region信息,需要开启HBase的临时开启CatalogJanitor功能,可以考虑先记录目前系统内的CatalogJanitor功能的状态,在修复完成后恢复这个状态。

4 结语

HBase是目前大数据技术栈的主要组件,主要承担数据的随机读写任务。HBase region是HBase用来实现负载均衡和可扩展性的重要概念。在HBase运行过程中,HBase 会自动执行region分裂、合并、上下线等操作,或者HBase的运维人员也会手动地进行这些操作。在操作的过程中,由于软硬件的故障,会导致region的rowkey的排布出现互相重叠的问题,导致读写HBase数据出现问题,这就是HBase Region Overlap问题。本文分析了产生问题的原因,并描述了重现问题、检测问题和解决问题的逻辑,对于保证HBase长期稳定的运行有比较大的帮助。未来会进一步完善处理逻辑,将其作为一个组件加入hbase hbck2 tools中。

猜你喜欢
故障过程
血脑屏障损伤在正常衰老过程中的作用
享受真实,享受过程
故障一点通
描写具体 再现过程
临终是个怎样的过程
奔驰R320车ABS、ESP故障灯异常点亮
在这个学习的过程中收获最大的是哪些,为什么?
故障一点通
故障一点通
故障一点通