HBaseにはhbck
という、リージョンやテーブルの整合性や完全性をチェックしたり、壊れていたりした場合に修復するツールがあります。この記事では、そのhbckの使い方や仕組みを説明したいと思います。バージョンはHBase 1.1.2 (HDP 2.5) をベースにしています。
HBaseのメタデータと実データについて
HBaseでは、メタデータ(HBaseテーブル)と実データ(HDFS)をそれぞれ管理しています。hbckの説明に入って行く前に、HBaseではどのようにデータを保存しているのかについて見てみましょう。
メタデータ
テーブルに関するメタデータは、HBaseのテーブルとして保存されています。そのテーブル名はhbase:meta
です。
このテーブルに対してスキャンすると以下のようになります。
hbase(main):001:0> scan "hbase:meta", {STARTROW => "test"}
ROW COLUMN+CELL
test,,1483946613382.2e2531f7c70a6fc178ac3472193ab26b. column=info:regioninfo, timestamp=1483946614406, value={ENCODED => 2e2531f7c70a6fc178ac3472193ab26b, NAME => 'test,,1483946613382.2e2531f7c70a6fc178ac3472193ab26b.',
STARTKEY => '', ENDKEY => 'a'}
test,,1483946613382.2e2531f7c70a6fc178ac3472193ab26b. column=info:seqnumDuringOpen, timestamp=1483946614849, value=\x00\x00\x00\x00\x00\x00\x00\x02
test,,1483946613382.2e2531f7c70a6fc178ac3472193ab26b. column=info:server, timestamp=1483946614849, value=sandbox.hortonworks.com:16020
test,,1483946613382.2e2531f7c70a6fc178ac3472193ab26b. column=info:serverstartcode, timestamp=1483946614849, value=1483940390908
test,a,1483946613382.0e984bc5624b8bd5d7f7e3c29fef38af. column=info:regioninfo, timestamp=1483946614406, value={ENCODED => 0e984bc5624b8bd5d7f7e3c29fef38af, NAME => 'test,a,1483946613382.0e984bc5624b8bd5d7f7e3c29fef38af.'
, STARTKEY => 'a', ENDKEY => ''}
test,a,1483946613382.0e984bc5624b8bd5d7f7e3c29fef38af. column=info:seqnumDuringOpen, timestamp=1483946614858, value=\x00\x00\x00\x00\x00\x00\x00\x02
test,a,1483946613382.0e984bc5624b8bd5d7f7e3c29fef38af. column=info:server, timestamp=1483946614858, value=sandbox.hortonworks.com:16020
test,a,1483946613382.0e984bc5624b8bd5d7f7e3c29fef38af. column=info:serverstartcode, timestamp=1483946614858, value=1483940390908
2 row(s) in 0.4040 seconds
これはtestという名前のテーブルのメタデータになります。1つリージョンに対して1つの列がマッピングされます。今回はリージョンが2つあるので、2つの列が表示されてるのが分かります。
hbase:metaのスキーマは以下になります。
列キー
列キーは以下のようなフォーマットで格納されています。
[table],[start key],[timestamp].[encoded region name]
[table]はテーブル名で、[region start key]はそのリージョンの開始キー、そして[timestamp]はリージョンが作成された時間です。最後の[encoded region name]はそのリージョンの名前を表していて、[table]と[region start key]と[timestamp]のハッシュをとってエンコードされたものです。
カラム
カラムはinfo:regioninfo
とinfo:seqnumDuringOpen
、info:server
、info:serverstartcode
などがあります。
info:regioninfoはエンコードされたリージョン名やその列キー、またはリージョンの開始キー/終了キーがなどの情報が含まれています。
info:seqnumDuringOpenはそのリージョンのデフォルトのレプリカIDのシーケンス番号が入っています。本筋とあまり関係がないので説明は省略します。
info:serverには、そのリージョンがアサインされているリージョンサーバの情報が入っています。
info:serverstartcodeには、そのリージョンがスタートした時間が入っています。
実データ
実データはHDFS上に格納されています。HBaseのデータディレクトリを見てみると以下のような構造になっています。
$ hdfs dfs -ls /apps/hbase/data
Found 9 items
drwxr-xr-x - hbase hdfs 0 2017-01-08 12:14 /hbase/.hbase-snapshot
drwxr-xr-x - hbase hdfs 0 2017-01-09 10:36 /hbase/.migration
drwxr-xr-x - hbase hdfs 0 2017-01-09 07:23 /apps/hbase/data/.tmp
drwxr-xr-x - hbase hdfs 0 2017-01-09 05:40 /apps/hbase/data/WALs
drwxr-xr-x - hbase hdfs 0 2017-01-09 05:50 /apps/hbase/data/archive
drwxr-xr-x - hbase hdfs 0 2016-10-25 07:49 /apps/hbase/data/data
-rw-r--r-- 1 hbase hdfs 42 2016-10-25 07:48 /apps/hbase/data/hbase.id
-rw-r--r-- 1 hbase hdfs 7 2016-10-25 07:48 /apps/hbase/data/hbase.version
drwxr-xr-x - hbase hdfs 0 2017-01-09 06:50 /apps/hbase/data/oldWALs
.hbase-snapshot
ディレクトリには、スナップショット関連のファイルが含まれています。.migration
ディレクトリはHBaseのアップグレードを行う際に用いられます。.tmp
ディレクトリは一時作業時に作られるファイルのためにあるディレクトリです。hbckもこのディレクトリを利用します。WALs
ディレクトリはすべてのリージョンサーバのアクティブなWALファイルが格納されているディレクトリです。archive
ディレクトリは.hbase-snapshotディレクトリも関連しますが、スナップショットのみで使われるディレクトリです。archiveディレクトリには、スナップショットのために必要なHFileが格納されてます。hbase.id
ファイルはクラスタのユニークなIDが書き込まれているファイルです。hbase.version
ファイルは名前の通りHBaseのバージョンが含まれているファイルです。oldWALs
ディレクトリはHBaseレプリケーションに関連したディレクトリです。アクティブなWALはWALsディレクトリにありますが、アクディブでないかつまだレプリケーションされてないWALファイルはoldWALsに格納されます。
HBaseの実際のデータはdata
ディレクトに格納されています。ここからはこのディレクトリにフォーカスして説明します。
dataディレクトリは以下のような構造になっています。
$ hdfs dfs -ls /apps/hbase/data/data
Found 2 items
drwxr-xr-x - hbase hdfs 0 2017-01-09 07:23 /apps/hbase/data/data/default
drwxr-xr-x - hbase hdfs 0 2016-10-25 07:49 /apps/hbase/data/data/hbase
dataディレクトリ以下には、ネームスペースのディレクトリがあります。この環境ではデフォルトのネームスペースであるdefault
と、HBaseのシステムテーブルが所属するネームスペースのhbase
があります。
それぞれのネームスペースのディレクトリをを見てみると以下のようになります。
$ hdfs dfs -ls /apps/hbase/data/data/default
Found 1 items
drwxr-xr-x - hbase hdfs 0 2017-01-09 07:23 /apps/hbase/data/data/default/test
$ hdfs dfs -ls /apps/hbase/data/data/hbase
Found 4 items
drwxr-xr-x - hbase hdfs 0 2016-10-25 07:49 /apps/hbase/data/data/hbase/acl
drwxr-xr-x - hbase hdfs 0 2016-10-25 07:49 /apps/hbase/data/data/hbase/backup
drwxr-xr-x - hbase hdfs 0 2016-10-25 07:48 /apps/hbase/data/data/hbase/meta
drwxr-xr-x - hbase hdfs 0 2016-10-25 07:49 /apps/hbase/data/data/hbase/namespace
ネームスペースのディレクトリの下には、テーブルのディレクトリがあります。この環境ではdefaultネームスペース以下にtest
テーブルがあり、hbaseネームスペース以下にはacl
テーブル、backup
テーブル、meta
テーブル、そしてnamespace
テーブルがあります。
さらにtestテーブルを見ていきます。
hdfs dfs -ls /apps/hbase/data/data/default/test
Found 4 items
drwxr-xr-x - hbase hdfs 0 2017-01-09 07:23 /apps/hbase/data/data/default/test/.tabledesc
drwxr-xr-x - hbase hdfs 0 2017-01-09 07:23 /apps/hbase/data/data/default/test/.tmp
drwxr-xr-x - hbase hdfs 0 2017-01-09 07:23 /apps/hbase/data/data/default/test/0e984bc5624b8bd5d7f7e3c29fef38af
drwxr-xr-x - hbase hdfs 0 2017-01-09 07:23 /apps/hbase/data/data/default/test/2e2531f7c70a6fc178ac3472193ab26b
.tabledesc
ディレクトリは、.tableinfo.000000xxxx
という名前のファイルが含まれていて、xxxxはシーケンス番号になっています。.tableinfoファイルには、hbaseのシェル上でdescribe
した時に取得できる情報と同じものが含まれています。例えば、ブロックエンコーディングタイプやブルームフィルターを使うかどうか、保持するバージョン数や圧縮などです。そして.tmp
ディレクトリは一時作業時に作られるファイルのためにあるディレクトリです。例えば.tableinfoファイルはまず.tmpディレクトリ以下で作成され、.tabledescディレククトリに移動されます。それ以外のディレクトリはエンコードされたリージョン名となっていて、リージョンのデータが格納されています。
リージョンのディレクトリは以下のようになっています。
hdfs dfs -ls -R /apps/hbase/data/data/default/test/0e984bc5624b8bd5d7f7e3c29fef38af
-rw-r--r-- 1 hbase hdfs 40 2017-01-09 07:23 /apps/hbase/data/data/default/test/0e984bc5624b8bd5d7f7e3c29fef38af/.regioninfo
drwxr-xr-x - hbase hdfs 0 2017-01-09 10:09 /apps/hbase/data/data/default/test/0e984bc5624b8bd5d7f7e3c29fef38af/.tmp
drwxr-xr-x - hbase hdfs 0 2017-01-09 10:09 /apps/hbase/data/data/default/test/0e984bc5624b8bd5d7f7e3c29fef38af/cf
-rw-r--r-- 1 hbase hdfs 4956 2017-01-09 10:09 /apps/hbase/data/data/default/test/0e984bc5624b8bd5d7f7e3c29fef38af/cf/bda632095b304a74866a0d99979448aa
-rw-r--r-- 1 hbase hdfs 4962 2017-01-09 10:09 /apps/hbase/data/data/default/test/0e984bc5624b8bd5d7f7e3c29fef38af/cf/ca33589a346943d88e09f4fe78416f5b
.regioninfo
ファイルはリージョンの情報が含まれています。.tmp
ディレクトリは一時作業時に作られるファイルのためにあるディレクトリでメジャーコンパクション等の処理で使われます。そしてカラムファミリcf
ディレクトリの下に実際のデータファイル(HFile)であるbda632095b304a74866a0d99979448aa
とca33589a346943d88e09f4fe78416f5b
ファイルがあります。
hbckの使い方について
それでは、HBaseの内部的なデータの持ち方について説明したので、hbckの使い方について説明します。
hbckの基本的な使い方は以下になります。
$ hbase hbck
このコマンドを実行すると最後にOKかINCONSISTENTが表示されます。INCONSISTENTが表示された場合はデータに不整合があるということになります。
下記のように-details
オプションをつけるとより詳細な説明が表示されます。
$ hbase hbck -details
以下のように特定のテーブルだけ指定して、チェック・修復を行うこともできます。
$ hbase hbck table1 table2
検出できる不整合とその直し方
検出できる不整合とその直し方をエラーメッセージ別に説明していきます。
メタデータ、アサイン系のエラーメッセージ
まず、はじめにメタデータやアサイン系の不整合についてです。
この不整合を検出するためにhbckは以下の情報を使います。
- 各リージョンサーバに実際にデプロイされているリージョンの情報
- hbase:metaの情報
- .regioninfoファイルの情報
基本的な考え方としては、HDFSに置かれている「.regioninfoファイルの情報」を正として修正を行います。ここで説明するオプションではHDFSのデータの変更はしません。
以下のオプションを使って不整合の修復を行います。
オプション | 説明 |
---|---|
-fix | リージョンのアサインメントの修復を行います。後方互換のために残されているオプションです。 |
-fixAssignments | リージョンのアサインメントの修復を行います。-fixを置き換えたものです。 |
-fixMeta | メタデータの修復を行います。 |
-fixEmptyMetaCells | hbase:metaのinfo:regioninfoカラムの内容が空のエントリを削除します。 |
-fixSplitParents | オフラインのsplit parentを強制的にオンラインにします。 |
以下、エラーメッセージとその修復方法になります。
"META region or some of its attributes are null."
hbase:metaのリージョンの情報がないか、その中の属性データが欠落している。
hbase:metaのリージョンの情報はZookeeper上に保存されていますがそれが無いか、情報が欠落している場合に起きるエラーです。この状態を修復するためには、クラスタを再起動するか、場合によっては特定のZookeeperのznodeをクリアする必要があります。
"hbase:meta, replicaId A is not found on any region."
レプリカIDがAのhbase:metaのリージョンがどのサーバにもデプロイされていない。
レプリカIDの説明は以下です。
HBaseは基本的には1つのリージョンは1つのリージョンサーバに割り当てられますが、Region Replicasという機能を使うことで、1つのリージョンに対してプライマリとセカンダリのレプリカを複数のサーバに割り当てることができます。その際にそれらのレプリカにIDが割り振られそれをレプリカIDと呼びます。Region Replicasについての詳細は以下をご覧ください。
このエラーは-fixAssignments
オプションを指定することで修復できます。このときhbckは、デプロイされていないリージョンをサーバにデプロイします。
"hbase:meta, replicaId A is found on more than one region."
レプリカIDがAのhbase:metaのリージョンが複数サーバにデプロイされている。
このエラーは-fixAssignments
オプションを指定することで修復できます。このときhbckは、重複してデプロイされている不必要なリージョンをクローズさせます。
"hbase:meta replicas are deployed in excess. Configured A, deployed B"
hbase:metaのレプリカが設定より多くデプロイされている。A個で設定されているが、実際にはB個デプロイされている。
このエラーは-fixAssignments
オプションを指定することで修復できます。このときhbckは、不必要なリージョンのレプリカをクローズさせます。
"Empty REGIONINFO_QUALIFIER found in hbase:meta"
hbase:metaの中でinfo:regioninfoカラムの内容が空。
このエラーは-fixEmptyMetaCells
オプションを指定することで修復できます。このときhbckは、info:regioninfoカラムが空の列を削除します。
"Region A, key=B, not on HDFS or in hbase:meta but deployed on X"
リージョンA(エンコードされたリージョン名B)は、HDFS(実データ)とhbase:metaにエントリがないのにサーバXにデプロイされている。
このエラーは-fixAssignments
オプションを指定することで修復できます。このときhbckは、そのリージョンをサーバからアンデプロイします。
"Region A on HDFS, but not listed in hbase:meta or deployed on any region server"
リージョンAは実データがHDFS上にはあるが、hbase:metaにエントリがなく、どのサーバにもデプロイされていない。
このエラーは-fixAssignments
オプションと-fixMeta
オプションを指定することで修復できます。このときhbckは、HDFS上の.regioninfoからhbase:metaのエントリを復旧し、そのリージョンをいずれかのサーバにアサインします。
"Region A not in META, but deployed on X"
リージョンAはhbase:metaにエントリがないのに、サーバXにデプロイされている(実データも存在する)。
このエラーは-fixAssignments
オプションと-fixMeta
オプションを指定することで修復できます。このときhbckは、HDFS上の.regioninfoからhbase:metaのエントリを復旧し、そのリージョンをいずれかのサーバに再アサインします。
"Region A found in META, but not in HDFS or deployed on any region server."
リージョンAはMETA上にはあるが、実データがHDFSに存在せず、サーバにもデプロイされていない。
このエラーは-fixMeta
オプションを指定することで修復できます。このときhbckは、META上からデータを削除します。
"Region A found in META, but not in HDFS, and deployed on X"
リージョンAはhbase:meta上にはあるが、実データがHDFSに存在せず、サーバXにデプロイされている。
このエラーは-fixAssignments
オプションと-fixMeta
オプションを指定することで修復できます。このときhbckは、hbase:meta上からデータを削除し、そのリージョンをサーバからアサインを外します。
"Region A not deployed on any region server."
リージョンAはどのサーバにもデプロイされていない。
このエラーは-fixAssignments
オプションを指定することで修復できます。このときhbckは、そのリージョンをいずれかのサーバに再アサインします。
"Region A should not be deployed according to META, but is deployed on X"
リージョンAはhbase:metaによるとどこにもデプロイされてないはずだが、実際にはサーバXにデプロイされている。
このエラーは-fixAssignments
オプションを指定することで修復できます。このときhbckは、そのリージョンをクローズし強制的にオフラインにします。
"Region A is listed in hbase:meta on region server X but is multiply assigned to region servers Y,Z"
リージョンAはhbase:metaに存在しサーバXにデプロイされてるはずだが、実際には複数のサーバYとZにデプロイされている。
このエラーは-fixAssignments
オプションを指定することで修復できます。このときhbckは、それらリージョンをクローズし強制的にオフラインにします。
"Region A listed in hbase:meta on region server X but found on region server Y"
リージョンAはhbase:metaに存在しサーバXにデプロイされてるはずだが、実際にはサーバYにデプロイされている。
このエラーは-fixAssignments
オプションを指定することで修復できます。このときhbckは、それらリージョンをクローズし強制的にオフラインにし、再アサインされるのを待ちます。
"Region A is a split parent in META, in HDFS, and not deployed on any region server. This could be transient."
リージョンAはhbase:metaとHDFS上ではsplit parentになってるが、どのサーバにもデプロイされてない。移行中の可能性もある。
リージョンが分割されると、オフラインになった親リージョンは自動的にクリーンアップされますが、たまに残ってしまう場合があります。このときその情報はhbase:metaにはあってHDFS上にデータは残っていますがサーバにデプロイされていない状態になります。このときに-fixSplitParents
オプションを指定してhbckを実行すると、分割された状態をリセットしてその親リージョンをオンラインにします。そしてさらにオーバラップ系のオプションを指定することで子リージョンとマージすることもできます。
まとめ
今回は、HBaseのメタデータと実データについて実際にどう格納されているかについて説明し、メタデータ、アサイン系のエラーメッセージとその直し方について書きました。次回はそれ以外のエラーメッセージとその直し方について説明します。