原創(chuàng):禪克
最近某應用反饋 HBase 數(shù)據插入數(shù)據后、查詢出現(xiàn)錯誤數(shù)據
現(xiàn)象如下:
有一行數(shù)據:
前面時間 T1 :插入3列
后面時間 T2 :插入1 列(通過 put 新值來更新某列數(shù)據)
scan 操作只能看到 時間點T1的 3 列數(shù)據,
get 操作只能看到時間點 T2 的 1 列最新數(shù)據
具體例子:
有一行數(shù)據 rowkey 是 591420001
時間點T1:插入數(shù)據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
詳細了解以及現(xiàn)象:
剛開始懷疑會不會是使用問題,應用查詢的時候,指定了版本;后來詢問了是否設置了多版本之類的情況,答案是沒有。經過溝通詢問,發(fā)現(xiàn)有些 rowkey 的數(shù)據是有問題,有些是正常的,這是一個非常重要的信息,也就是說異常的Case只會發(fā)生在某些行數(shù)據中。
由此信息懷疑問題是否和 rowkey 分布的 Region 有關系,
根據對 HBase 的了解,大概猜測出了 Region 很可能發(fā)生了重疊的情況。
Region 重疊
Region 重疊,英文叫做 region overlap,意思是region 范圍發(fā)生了交叉,
正常region
~10
10~20
20~30
30~40
40~
重疊region
~10
10~20
15~25
20~30
30~40
40~
如上 1020,1525,20~30 就發(fā)生了重疊
空洞 region
region 還有一個常見的問題,叫做 region 空洞 hole
~10
10~20
30~40
40~
如上 20~30 就區(qū)間沒有了,也就是發(fā)生了所謂的 hole,
region 空洞通常是 region 沒有 assign 成功導致
時間點 T1 的數(shù)據插入的數(shù)據從 hbase:meta 表中找到 regionA,
時間點 T2 的數(shù)據插入的數(shù)據從 hbase:meta 表中找到 regionB,
5914200010001 這個 rowkey 同時屬于 regionA 和 RegionB
檢查集群,果然驗證了自己的猜測

上圖可以看到使用紅線框起來的這個 region 是有問題的,
剛開始的時候,時間點 T1 插入數(shù)據到了正常的 region 中,
時間點 T2,插入數(shù)據,正好到5192-5294 這個異常的 region 中去了。
所以導致 scan 和 get 結果不一致。
這個異常的 Region 怎么來的?應用懷疑是 HBase split 出現(xiàn)異常導致的,真的是 HBase 自己 split 出來的嗎?答案是否定的。
表是預先分區(qū)的,指定的每個 splitkey 都為 7位長度(比如4750000,4800000),
rowkey 設計上面確保是 13 位長度,異常的 region 的 startkey/endkey 只有 4 位長度, 基本上可以排除 split 出來的可能性.
因為region的startkey 要不是預先分區(qū)指定的值,要不是 split 時候取的 splitPonit 值(也就是 region下面列族中最大的 hfile midkey) ,所以幾乎不可能是 split 異常導致的
當時有個大膽的推測,會不會是這個 region 是誰拷貝了一個其它表或者之前的表的 region 目錄,放在表目錄下,然后一頓操作猛如虎,把這個給上線了。。。
后來 check了 NameNode 的審計日志,果然發(fā)現(xiàn)是被人拷貝過來的。。。
通過觀察這個 region 的 .regioninfo 信息,發(fā)現(xiàn)這個region 是數(shù)個月之前的,后來被人為拷貝過來的, 具體為啥拷貝就不細說了。。。
這個 case 非常有意思, 會涉及到 HBase 的 hbck工具,hfile工具,如何查看 master 頁面,hbase:meta 元數(shù)據信息,hbase 表的目錄結構等等信息
明白了問題的現(xiàn)象和原因以后,我們來處理這個問題呢?
處理思路:
盡快恢復業(yè)務!
下線錯誤 region -> 修復 hbase:meta -> move region 目錄 -> 恢復數(shù)據
這個問題非常考驗對 HBase 的理解以及工具的使用。
1、unassign region :下線 region
2、move region 目錄,將出問題的 region 拷貝走
(這個目錄中的數(shù)據后續(xù)可能還需要導入)
3、scan 'hbase:meta' 找到出問題的 region 信息,從 hbase:meta 中刪除
(小心操作)
4、導入數(shù)據 使用 dobulkload 將出問題的 region hfile 重新導入進去
因為錯誤的region 是被拷貝過來的,需要研究一下這個錯誤的 region 當時拷貝過來的時候,是否含有 hfile,也就是舊的數(shù)據;一般來說舊數(shù)據按理說我們是不需要,我們需要的是拷貝過來的錯誤的 region 上線后面又寫入的這部分數(shù)據,
這部分數(shù)據雖然寫到了錯誤的 region,但確實是需要的數(shù)據。
這塊的處理邏輯是需要推斷,稍微判斷失誤,就可能會丟數(shù)據,或者導入不該導入的數(shù)據進來。
首先使用 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 中打印出來的信息,可以發(fā)現(xiàn) hfile 中的數(shù)據都是后寫入的,根據 rowkey 信息(內含時間戳)以及 KV 的 timestamp 字段來判斷。到此 HBase 其實已經可以正常讀寫了。不過 此時 hbase 的 hmaster 中還有臟數(shù)據,比如頁面中還會顯示這個錯誤的 region
5、根據需要決定是否重啟 HMaster,清理 HMaster 內存中的臟數(shù)據
如上是大概的推測:是否可以解決問題?線上環(huán)境還是需要非常謹慎的。
制造 Region overlap/ 復現(xiàn)問題
首先我們來”制造”一個類似的問題,也就是生成一個錯誤的region,制造region overlap(當時環(huán)境使用的是2.x 的某個早期版本,hbck2 還不完善),復現(xiàn)問題:
- 首先創(chuàng)建一個表
create 'test','f', SPLITS => ['05', '15', '25']
- 然后將這個表目錄拷貝出來
假設拷貝到 /tmp/xxx/test
- 刪除表
disbale 'test'
drop 'test'
4)重新創(chuàng)建表(不同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
執(zhí)行命令
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 中了,此時就成功復現(xiàn)了 region overlap
**解決流程 **
- 下線錯誤
region:進入hbase shell對出問題的region執(zhí)行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 表中臟數(shù)據清理以后客戶端讀寫就獲取不到錯誤 region 了
5.數(shù)據導入
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 元數(shù)據原理和上下線、讀寫流程等都需要有一定的了解。