AIOps 一场颠覆传统运维的盛筵
841
2022-10-02
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=1595252559734, value=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
**解决流程 **
下线错误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 文件
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
最后问题得以解决。
这个问题,需要对 unassign、hbck、region 如何上下线,hbase 表目录结构,hfile 工具,dobulkload 工具,.regioninfo、hbase:meta 等工具链
HBase 元数据原理和上下线、读写流程等都需要有一定的了解。
发表评论
暂时没有评论,来抢沙发吧~