HBase 运维|HBase Region 重叠问题处理

最近某应用反馈 HBase 数据插入数据后、查询出现错误数据

现象如下:

有一行数据:

前面时间 T1 :插入3列

后面时间 T2 :插入1 列(通过 put 新值来更新某列数据)

scan 操作只能看到 时间点T1的 3 列数据,

get 操作只能看到时间点 T2 的 1 列最新数据

具体例子:

有一行数据 rowkey 是 591420001

时间点T1:插入数据c1-c3 共3列,注意此时 c2=2

ROW                                 COLUMN+CELL
5914200010001 column=f:c1, timestamp=1595252551656, value=1
5914200010001 column=f:c2, timestamp=1595252551656, value=2
5914200010001 column=f:c3, timestamp=1595252551656, value=3


时间点T2 插入c2值为 2-1:

 ROW                                 COLUMN+CELL
5914200010001 column=f:c2, timestamp=1595252559734, value=2-1


正确的 scan 或者 get 应该是:

ROW                                 COLUMN+CELL
5914200010001 column=f:c1, timestamp=1595252551656, value=1
5914200010001 column=f:c2, timestamp=1595252559734, value=2-1
5914200010001 column=f:c3, timestamp=1595252551656, value=3


实际情况 scan 出来的结果:

 5914200010001                          column=f:c1, timestamp=1595252551656, value=1
5914200010001 column=f:c2, timestamp=1595252559734, value=2
5914200010001 column=f:c3, timestamp=1595252551656, value=3


get 出来的结果是:

5914200010001            column=f:c2, timestamp=1595252559734value=2-1


详细了解以及现象:

刚开始怀疑会不会是使用问题,应用查询的时候,指定了版本;后来询问了是否设置了多版本之类的情况,答案是没有。经过沟通询问,发现有些 rowkey 的数据是有问题,有些是正常的,这是一个非常重要的信息,也就是说异常的Case只会发生在某些行数据中。

由此信息怀疑问题是否和 rowkey 分布的 Region 有关系,

根据对 HBase 的了解,大概猜测出了 Region 很可能发生了重叠的情况。

Region 重叠

Region 重叠,英文叫做 region overlap,意思是region 范围发生了交叉,

正常region

 ~10 10~2020~3030~40 40~


重叠region

 ~10 10~2015~25 20~3030~40 40~


如上 10~20,15~25,20~30 就发生了重叠

空洞 region

region 还有一个常见的问题,叫做 region 空洞 hole

 ~10 10~2030~40 40~


如上 20~30 就区间没有了,也就是发生了所谓的 hole

region 空洞通常是 region 没有 assign 成功导致

时间点 T1 的数据插入的数据从 hbase:meta 表中找到 regionA

时间点 T2 的数据插入的数据从 hbase:meta 表中找到 regionB

5914200010001 这个 rowkey 同时属于 regionA 和 RegionB 

检查集群,果然验证了自己的猜测


上图可以看到使用红线框起来的这个 region 是有问题的,

刚开始的时候,时间点 T1 插入数据到了正常的 region 中,

时间点 T2,插入数据,正好到5192-5294 这个异常的 region 中去了。

所以导致 scan 和 get 结果不一致。

这个异常的 Region 怎么来的?应用怀疑是 HBase split 出现异常导致的,真的是 HBase 自己 split 出来的吗?答案是否定的。

表是预先分区的,指定的每个 splitkey 都为 7位长度(比如4750000,4800000),

rowkey 设计上面确保是 13 位长度,异常的 region 的 startkey/endkey 只有 4 位长度, 基本上可以排除 split 出来的可能性.

因为region的startkey 要不是预先分区指定的值,要不是 split 时候取的 splitPonit 值(也就是 region下面列族中最大的 hfile midkey) ,所以几乎不可能是 split 异常导致的

当时有个大胆的推测,会不会是这个 region 是谁拷贝了一个其它表或者之前的表的 region 目录,放在表目录下,然后一顿操作猛如虎,把这个给上线了。。。

后来 check 了 NameNode 的审计日志,果然发现是被人拷贝过来的。。。

通过观察这个 region 的 .regioninfo 信息,发现这个region 是数个月之前的,后来被人为拷贝过来的, 具体为啥拷贝就不细说了。。。

这个 case 非常有意思, 会涉及到 HBase 的 hbck工具,hfile工具,如何查看 master 页面,hbase:meta 元数据信息,hbase 表的目录结构等等信息

明白了问题的现象和原因以后,我们来处理这个问题呢?

处理思路:

尽快恢复业务!

下线错误 region -> 修复 hbase:meta -> move  region 目录 -> 恢复数据

这个问题非常考验对 HBase 的理解以及工具的使用。

1、unassign region :下线 region

2、move region 目录,将出问题的 region 拷贝走

(这个目录中的数据后续可能还需要导入)

3、scan 'hbase:meta' 找到出问题的 region 信息,从 hbase:meta 中删除

(小心操作)

4、导入数据 使用 dobulkload 将出问题的 region hfile 重新导入进去

因为错误的region 是被拷贝过来的,需要研究一下这个错误的 region 当时拷贝过来的时候,是否含有 hfile,也就是旧的数据;一般来说旧数据按理说我们是不需要,我们需要的是拷贝过来的错误的 region 上线后面又写入的这部分数据,

这部分数据虽然写到了错误的 region,但确实是需要的数据。

这块的处理逻辑是需要推断,稍微判断失误,就可能会丢数据,或者导入不该导入的数据进来。

首先使用 hbase hfile 工具,来检查一下这个错误的 region 下面的 hfile 的信息,

可能会使用到如下命令:

查看某个hfile 基本信息,比如startkey/endkey/midkey,又多少key,最大,最小,平均长度,时间戳等等
$ hbase hfile -f hfile_path -s 打印kv$ hbase hfile -f hfile_path -p打印key$ hbase hfile -f hfile_path -e

本案例中从这些 hfile 中打印出来的信息,可以发现 hfile 中的数据都是后写入的,根据 rowkey 信息(内含时间戳)以及 KV 的 timestamp 字段来判断。到此 HBase 其实已经可以正常读写了。不过 此时 hbase 的 hmaster 中还有脏数据,比如页面中还会显示这个错误的 region

5、根据需要决定是否重启 HMaster,清理 HMaster 内存中的脏数据

如上是大概的推测:是否可以解决问题?线上环境还是需要非常谨慎的。

制造 Region overlap/ 复现问题

首先我们来”制造”一个类似的问题,也就是生成一个错误的region,制造region overlap(当时环境使用的是2.x 的某个早期版本,hbck2 还不完善),复现问题:

1) 首先创建一个表

create 'test','f'SPLITS => ['05''15''25']

2) 然后将这个表目录拷贝出来

假设拷贝到 /tmp/xxx/test

3) 删除表

disbale 'test'drop 'test'

4)重新创建表(不同splitkeys)

create 'test''f'SPLITS => ['10''20''30']

5)然后选取上一次建表的region目录拷贝到新表目录中

比如:

hdfs dfs -cp /tmp/xxx/test/4f3cab0063decfac00755c88337da380 /apps/hbase/data/data/default/test/


6)上线有问题的 region

执行命令

 hbase hbck -j $hbase_home/hbase-operator-tools/hbase-hbck***.jar addFsRegionsMissingInMeta default:test


如上命令的意思是根据 hdfs 中的 region 目录等信息加载到 hbase:meta 表中

7)重启 hmaster

8)上线这个有问题的 reigon

hbase hbck -j  $hbase_home/hbase-operator-tools//hbase-hbck***.jar assigns 4f3cab0063decfac00755c88337da380


查看 hmaster 界面,就可以成功看到 ` region overlap` 重叠的情况了

然后 scan hbase:meta 就可以成功看到 这个错误的 region 信息也存在 hbase:meta 中了,此时就成功复现了 region overlap

**解决流程 **

  1. 下线错误region:进入 hbase shell  对出问题的 region执行 unassign 'regionanme'

2.移动错误 region 目录,

例如移动到 hdfs://ns1/tmp/下新建一个目录放进去

HBase 目录结构如下

/apps/hbase/data/data/default/test/regionname/f/hfile

data 表目录

default:命名空间

test:表名

regionname:region目录

region 目录下面有.regioninfo

f:列族目录

hfile: 为 hfile 文件

  1. scan 'hbase:meta',{STARTROW => 'tablename,591420001000',LIMIT => 100} ,这里row填有问题的前面的row,

可能提示遮挡问题有问题,可以追加到文件里,从文件里复制

命令:echo “scan ‘hbase:meta’,{STARTROW => ‘tablename,591420001000’,LIMIT => 100}” hbase shell > hbase.txt

4.deleteall 'hbase:meta','tablename,rowkey.有问题的 region.’

示例命令:deleteall 'hbase:meta','test,5192,1578035374274. *****6bdd9b41aefefd0f89c.'

hbase:meta 表中脏数据清理以后客户端读写就获取不到错误 region 了

5.数据导入

hbase org.apache.hadoop.hbase.mapreduce.LoadIncrementalHFiles "/tmp/ hbase-loaddata /******89c/ " "t"


示例命令: 

hbase org.apache.hadoop.hbase.mapreduce.LoadIncrementalHFiles " /tmp/hbase-loaddata/*****6bdd9b41aefefd0f89c " "test"

6、重启 `hmaster

最后问题得以解决。

这个问题,需要对 unassignhbckregion 如何上下线,hbase 表目录结构,hfile 工具,dobulkload 工具,.regioninfohbase:meta 等工具链

HBase 元数据原理和上下线、读写流程等都需要有一定的了解。


本文分享自微信公众号 - HBase工作笔记(HBase-Notes)。
如有侵权,请联系 [email protected] 删除。
本文参与“OSC源创计划”,欢迎正在阅读的你也加入,一起分享。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章