本記事は Distributed computing (Apache Spark, Hadoop, Kafka, …) Advent Calendar 2019 21日目の記事です。
Clouderaサポートの小林です。本記事では、CDH 6やHDP 3に含まれるApache HBase 2(以下HBase 2あるいは単にHBaseとします)のデータ不整合を修復する新しいツール、HBCK2について以下の構成で紹介します。
- HBCK2とは何か
- HBCK2のコンセプト
- HBCK2の利用例
HBCK2とは何か
HBase 2には、リージョンやテーブルの不整合を修復するためのツールが同梱されていません。1系からあったhbckはリードオンリー、つまりあくまで不整合をレポートするだけのツールとなったためです(3系では完全になくなる予定です)。
その代わり、HBaseのコミュニティでは修復ツールをHBaseのプロジェクトとは別に開発・管理する道を選びました。それがhbase-operator-tools配下にあるHBCK2です。
https://github.com/apache/hbase-operator-tools/tree/master/hbase-hbck2
HBCK2のコンセプト
HBCK2には旧来のhbckと比べて以下のような違いがあります。
- HBase本体とは別に提供される
- 不整合のレポート機能はなく、修復のみ行うツールである
- やたらめったら使うべきではない
それぞれ簡単に見ていきます。
1. HBase本体とは別に提供される
別プロジェクトに分離したことで、修復ツールだけのリリースが可能になりました。つまり、サーバーサイドに変更を加えることなくクライアントで新しいバージョンの修復ツールが使えるようになります。現時点で公開されているバイナリは2019年9月にリリースされた1.0です(注: Clouderaのサブスクリプションを購入されている方は、サポートチームから提供されるバイナリをご利用ください)。
https://hbase.apache.org/downloads.html
クライアントで最新バージョンをビルドして使うこともできます。この場合は $ mvn install
で終わりです。生成されたjarを実行すると、ヘルプが出てきます。
$ hbase hbck -j ~/hbase-operator-tools/hbase-hbck2/target/hbase-hbck2-1.0.0-SNAPSHOT.jar
2. 不整合のレポート機能はなく、修復のみ行うツールである
旧来のhbckは、HMaster、hbase:meta、各RegionServerが持っている情報を統合し、データの不整合を報告してくれました。それに応じてユーザーは、hbckが用意する修復コマンドを選んで実行していたのです。しかしHBCK2にはレポート機能がありません。代わりにHMasterのUIで移動中のリージョンやオーバーラップしているリージョンを報告してくれますが、現時点(2019年12月現在)では旧来のhbckをレポートのみの用途で使っているのが実際です。それに加え、HMasterのログ、scan 'hbase:meta'
や hdfs dfs -ls -R /hbase
を収集し、HMaster、hbase:meta、HDFSの三箇所で持っているデータの状態を把握しましょう。それを元に、HBCK2で直すサブコマンドを選んでいくのがセオリーです。
3. やたらめったら使うべきではない
旧来のhbckには -fix
や -repair
といったそれさえ流せばなんとかしてくれそうな雰囲気を醸し出しているコマンドが存在していました。しかしながらこれらは往々にしてうまく動かず(正しく使われなかったというのもあり)、今以上の不整合を作り出してしまうケースが多々見られました(実装された当初はうまく動くことが期待されていたのですが、現実はそう甘くなかったようです)。
一方でHBCK2は、運用者が今発生している問題を “正しく” 認識していることを前提に設計されています。つまり、「必要なときに必要なコマンドのみを使うべき」としています(以下READMEより引用)。
While hbck1 performed analysis reporting your cluster GOOD or BAD, HBCK2 is less presumptious. In hbase-2.x, the operator figures what needs fixing and then uses tooling including HBCK2 to do fixup. The operator may have to go a few rounds of back and forth running HBCK2 then checking cluster state.
HBCK2の利用例
さて、以下ではいくつかのサンプルケースを紹介してHBCK2の機能を使うべき状況を説明します。
まずよくあるのが hbase:meta や hbase:namespace といったシステムテーブルのアサインがスタックし、HMasterの起動が完了しないという状況です。HMasterのログには以下のような出力が繰り返し出ているケースです。
2018-10-01 22:07:42,792 WARN org.apache.hadoop.hbase.master.HMaster: hbase:meta,,1.1588230740 is NOT online; state={1588230740 state=CLOSING, ts=1538456302300, server=ve1017.example.org,22101,1538449648131}; ServerCrashProcedures=true. Master startup cannot progress, in holding-pattern until region onlined.
HMasterが起動しきらないと、クライアントからのリクエストを受け付けることができません。厳密にはリージョンの読み書きはRegionServerが受け持つため可能なのですが、テーブル作成やスナップショットの取得などの管理コマンドが動作しません。このようなケースでは、HBCK2の assigns コマンドを使って強制的にアサインしましょう。以下は hbase:meta のリージョンをアサインする例です(metaのリージョンは常に 1588230740 です)。
$ hbase hbck -j <HBCK2 jar> assigns 1588230740
コマンドを実行すると、コンソールには [x] という値が返ってきます。この x
はHMasterが実行する処理の単位(Procedure Id)を意味します。このidを元にHMasterのログを確認し、処理が正しく実行されているか確認しましょう。
21:17:02.498 [main] INFO org.apache.hbase.CDHVersion - Converting 2.1.0-cdh6.3.2 to Apache 2.1.4 version.
[3]
hbase:meta
と hbase:namespace
のアサインが完了し、ログに以下のように出力されればHMasterの起動は完了です。
2019-11-27 21:17:14,071 INFO org.apache.hadoop.hbase.master.HMaster: Master has completed initialization 14.597sec
hbase shellがもつassign
コマンドとHBCK2のassigns
の違いは何でしょうか。前者は、HMasterが起動していなければ使用できません。コプロセッサーのチェックやACLのチェックが入るためです。また、前者はリージョンを一つずつしかアサインできません。
一方で後者はコプロセッサーやACLのチェックをスキップします。また、複数リージョンを指定することでバルクアサインが可能です。原則として、HMasterが起動している限りはhbase shellのassign
を使用するのが無難と考えます。
次に、長らくHBaseを運用してきたユーザーがよく陥りやすいのがOfflineMetaRepair
(以下OMR)を用いてしまうケースです。OMRはhbase:meta
をゼロから作り直すツールですが、旧来のOMRを2系のHBaseに対して使うとhbase:meta
を壊して異常終了するバグがあります(HBASE-21665)。
このようなケースではaddFsRegionsMissingInMeta
を使いましょう。OMRのバグは、「HDFSにはリージョンが存在するのにhbase:meta
には対応する行がない」という状況を作り出します。問題がどのリージョンについて発生しているのかを把握し、対象のリージョンをについてのみhbase:meta
に新しくエントリを追加してくれるのがこのコマンドです。以下のように、リージョンに対応するテーブル名を指定することで hbase:meta
が修復されます。
$ hbase hbck -j <HBCK2 jar> addFsRegionsMissingInMeta <NAMESPACE:TABLENAME>
コマンドが完了したら、HMasterの再起動と当該リージョンを明示的にアサインすることで作業は完了です。アサイン作業はHBCK2を使っても構いませんし、hbase shellから実行してもよいでしょう。
$ hbase shell
hbase> assign '<encoded region name>'
以上、まだまだコマンドがあるのですが、長くなったのでひとまずここまでとします。その他のコマンドについてもやはりやたらめったら使うものではないため、内部的に何をするものなのか、実行後にどういう状態を期待するのか、という理解ができている場合に限り使うようにしてください。