Apache HBase ブック

改訂履歴
改訂 0.91.0-SNAPSHOT  
Adding first cuts at Configuration, Getting Started, Data Model
改訂 0.89.20100924 2010 年 10 月 5 日stack
Initial layout

概要

これは Apache HBase の公式ブックです。Apache HBase は、Apache HadoopApache ZooKeeper を土台として構築された分散型でバージョン管理された列指向のデータベースです。


目次

序文
1. スタートガイド
1.1. はじめに
1.2. クイックスタートガイド
1.2.1. 最新の安定版リリースのダウンロードと展開
1.2.2. HBase の起動
1.2.3. Shell による操作
1.2.4. HBase の停止
1.2.5. 次は
1.3. 通常のスタートガイド
1.3.1. 必要なもの
1.3.2. HBase の実行モード: スタンドアロンモードと分散モード
1.3.3. 設定例
2. アップグレード
2.1. HBase 0.20.x または 0.89.x から HBase 0.90.x へのアップグレード
3. 設定
3.1. hbase-site.xmlhbase-default.xml
3.1.1. HBase のデフォルト設定
3.2. hbase-env.sh
3.3. log4j.properties
3.4. 重要な設定
3.4.1. 必要な設定
3.4.2. 推奨設定
3.5. HBase クラスタに接続するクライアントおよびクライアントの依存関係
3.5.1. Java クライアントの設定
4. HBase Shell
4.1. スクリプトの実行
4.2. Shell の使い方
4.2.1. irbrc
4.2.2. LOG の日付からタイムスタンプへの変換
4.2.3. デバッグ
5. HBase のビルド
5.1. Apache の Maven リポジトリへの HBase リリースの追加
6. HBase と MapReduce
6.1. デフォルトの HBase MapReduce スプリッタ
6.2. HBase Input MapReduce の例
6.3. 1 つの MapReduce ジョブでのほかの複数の HBase テーブルへのアクセス
7. HBase とスキーマ設計
7.1. スキーマの作成
7.2. 列ファミリの数について
7.3. 単調増加する行キー/時系列データ
7.4. 行と列のサイズを最小限に抑える
7.5. テーブルの作成: リージョンの事前作成
8. メトリクス
8.1. メトリクスのセットアップ
8.2. リージョンサーバーのメトリクス
8.2.1. hbase.regionserver.blockCacheCount
8.2.2. hbase.regionserver.blockCacheFree
8.2.3. hbase.regionserver.blockCacheHitRatio
8.2.4. hbase.regionserver.blockCacheSize
8.2.5. hbase.regionserver.fsReadLatency_avg_time
8.2.6. hbase.regionserver.fsReadLatency_num_ops
8.2.7. hbase.regionserver.fsSyncLatency_avg_time
8.2.8. hbase.regionserver.fsSyncLatency_num_ops
8.2.9. hbase.regionserver.fsWriteLatency_avg_time
8.2.10. hbase.regionserver.fsWriteLatency_num_ops
8.2.11. hbase.regionserver.memstoreSizeMB
8.2.12. hbase.regionserver.regions
8.2.13. hbase.regionserver.requests
8.2.14. hbase.regionserver.storeFileIndexSizeMB
8.2.15. hbase.regionserver.stores
9. クラスタレプリケーション
10. データモデル
10.1. テーブル
10.2. 行
10.3. 列ファミリ
10.4. セル
10.5. バージョン
10.5.1. バージョンと HBase での各種操作
10.5.2. 現時点での制限事項
11. アーキテクチャ
11.1. デーモン
11.1.1. Master
11.1.2. リージョンサーバー
11.2. リージョン
11.2.1. リージョンのサイズ
11.2.2. リージョンの分割
11.2.3. リージョンのロードバランサ
11.2.4. Store
12. 先行書き込みログ (WAL)
12.1. HBase の WAL の目的
12.2. WAL の分割
12.2.1. hbase.hlog.split.skip.errors
12.2.2. クラッシュしたリージョンサーバーの WAL を分割する際、EOFExceptions はどのように扱われるか
13. パフォーマンスチューニング
13.1. Java
13.1.1. ガベージコレクタと HBase
13.2. 設定
13.2.1. リージョンの数
13.2.2. コンパクションの管理
13.2.3. 圧縮
13.3. 列ファミリの数
13.4. データの集中
13.5. バッチロード
13.6. HBase クライアント
13.6.1. AutoFlush
13.6.2. Scan のキャッシュ
13.6.3. ResultScanner のクローズ
13.6.4. ブロックキャッシュ
14. ブルームフィルタ
14.1. 設定
14.1.1. HColumnDescriptor のオプション
14.1.2. io.hfile.bloom.enabled グローバル kill スイッチ
14.1.3. io.hfile.bloom.error.rate
14.1.4. io.hfile.bloom.max.fold
14.2. ブルームフィルタの StoreFile でのフットプリント
14.2.1. StoreFileFileInfo データ構造内の BloomFilter
14.2.2. StoreFile メタデータ内の BloomFilter エントリ
A. ツール
A.1. HBase hbck
A.2. HFile ツール
A.3. WAL ツール
A.3.1. HLog ツール
A.4. 圧縮ツール
B. HBase での圧縮
B.1. CompressionTest ツール
B.2. hbase.regionserver.codecs
B.3. LZO
B.4. GZIP
C. FAQ
D. YCSB: The Yahoo! Cloud Serving Benchmark と HBase
索引

序文

このブックは、本書が同梱されているバージョンの HBase の公式ガイドとなることを意図して書かれています。このドキュメントが対象としているのは HBase バージョン 0.91.0-SNAPSHOT です。このブックでは、対象となる HBase のバージョンがリリースされた時点での HBase のトピックに関する最終的な情報を見つけることができるほか、適切な情報が記載された javadocJIRA、または wiki へのポインタが用意されています。

このブックの執筆は現在進行中です。まだ多くの部分が未完成ですが、不足している部分は時間とともに埋められていくはずです。このブックに追加したいことがあったら、ぜひ HBase JIRA にパッチを上げてください。

第1章 スタートガイド

1.1. はじめに

クイックスタートガイド」では、ローカルファイルシステムを使った HBase のシングルノードインスタンスをセットアップして実行する方法について説明します。「通常のスタートガイド」では、HDFS 上に分散モードで HBbase をセットアップして実行する方法について説明します。

1.2. クイックスタートガイド

このガイドでは、ローカルファイルシステムを使うスタンドアロンの HBase インスタンスをセットアップする方法について説明します。具体的には、HBase Shell を使ったテーブルの作成、行の挿入、クリーンアップ、スタンドアロン HBase インスタンスのシャットダウンを実行します。以下で説明する操作の所要時間は (ダウンロードにかかる時間は除いて) 10 分足らずです。

1.2.1. 最新の安定版リリースのダウンロードと展開

Apache ダウンロードミラーサイトの一覧で適切なダウンロードサイトを選択します。通常は、一番上に表示されるリンクをクリックします。HBase Releases のページが表示されます。stable という名前のフォルダをクリックし、次に hbase-0.91.0-SNAPSHOT.tar.gz のように .tar.gz で終わる名前のファイルをローカルファイルシステムにダウンロードします。

次の要領で、ダウンロードしたファイルを解凍・展開し、展開後に作成されたディレクトリに移動します。

$ tar xfz hbase-0.91.0-SNAPSHOT.tar.gz
$ cd hbase-0.91.0-SNAPSHOT

これで HBase を起動する準備は整いました。ただし、HBase を起動する前に、必要に応じて conf/hbase-site.xml を編集し、HBase の書き込み先のディレクトリを hbase.rootdir で設定しておきます。


<?xml version="1.0"?>
<?xml-stylesheet type="text/xsl" href="configuration.xsl"?>
<configuration>
  <property>
    <name>hbase.rootdir</name>
    <value>file:///DIRECTORY/hbase</value>
  </property>
</configuration>

上の DIRECTORY の部分を、HBase がデータを格納するために使うディレクトリへのパスで置き換えてください。デフォルトでは、hbase.rootdir/tmp/hbase-${user.name} に設定されているので、サーバーを再起動するとすべてのデータが失われます (ほとんどのオペレーティングシステムは再起動時に /tmp の内容を消去します)。

1.2.2. HBase の起動

次のコマンドを実行し、HBase を起動します。

$ ./bin/start-hbase.sh
starting Master, logging to logs/hbase-user-master-example.org.out

これで、スタンドアロンの HBase のインスタンスが実行中になります。スタンドアロンモードでは、HBase はすべてのデーモン、すなわち HBase デーモンと ZooKeeper デーモンを 1 つの JVM 内で実行します。HBase のログは logs サブディレクトリにあります。HBase の起動時に問題があったら、ログを参照してください。

java はインストールされていますか?

上で説明した手順は、バージョン 1.6 の Oracle java がコンピュータにインストールされていて、java プログラムがパス内で見つかること、すなわち「java」と入力した時に、java プログラムのオプションが表示されることを前提にしています (HBase では java 6 が必要です)。java プログラムのオプションが表示されない場合、HBase は起動しません。この場合は、java をインストールし、conf/hbase-env.sh を編集して、JAVA_HOME の行をアンコメントし、java のインストール先を指すようにします。その後、上で説明した HBase の起動手順をやり直してください。

1.2.3. Shell による操作

HBase Shell を介して、実行中の HBase に接続します。

$ ./bin/hbase shell
HBase Shell; enter 'help<RETURN>' for list of supported commands.
Type "exit<RETURN>" to leave the HBase Shell
Version: 0.90.0, r1001068, Fri Sep 24 13:55:42 PDT 2010

hbase(main):001:0> 

help」と入力して <RETURN> キーを押し、シェルのコマンドとオプションの一覧を表示します。help コマンドの出力のうち、少なくとも最後のいくつかのパラグラフには目を通し、HBase Shell での変数やコマンドの引数の入力の方法、特にテーブル名、行、列などを引用符でどのように囲まなければならないかについて、しっかりと理解しておきましょう。

cf という名前の列ファミリを 1 つ持つ test という名前のテーブルを作成します。テーブルが作成されたことを確認するためにすべてのテーブルを表示し、次にいくつか値を挿入します。

hbase(main):003:0> create 'test', 'cf'
0 row(s) in 1.2200 seconds
hbase(main):003:0> list 'table'
test
1 row(s) in 0.0550 seconds
hbase(main):004:0> put 'test', 'row1', 'cf:a', 'value1'
0 row(s) in 0.0560 seconds
hbase(main):005:0> put 'test', 'row2', 'cf:b', 'value2'
0 row(s) in 0.0370 seconds
hbase(main):006:0> put 'test', 'row3', 'cf:c', 'value3'
0 row(s) in 0.0450 seconds

ここでは、1 回に 1 つずつ、3 つの値を挿入しています。最初の操作では、row1 に列 cf:a を値 value1 で挿入しています。HBase の列は、列ファミリプリフィックス (現在の例では cf) とそれに続くコロン (:)、さらに列修飾子サフィックス (現在の例では a) から構成されます。

実際にデータが挿入されていることを確認します。

次のように入力してテーブルをスキャンします。

hbase(main):007:0> scan 'test'
ROW        COLUMN+CELL
row1       column=cf:a, timestamp=1288380727188, value=value1
row2       column=cf:b, timestamp=1288380738440, value=value2
row3       column=cf:c, timestamp=1288380747365, value=value3
3 row(s) in 0.0590 seconds

1 行だけを取得します。

hbase(main):008:0> get 'test', 'row1'
COLUMN      CELL
cf:a        timestamp=1288380727188, value=value1
1 row(s) in 0.0400 seconds

テーブルを無効にして削除します。これまでに行った操作の結果はすべてクリーンアップされます。

hbase(main):012:0> disable 'test'
0 row(s) in 1.0930 seconds
hbase(main):013:0> drop 'test'
0 row(s) in 0.0770 seconds 

「exit」と入力して Shell を終了します。

hbase(main):014:0> exit

1.2.4. HBase の停止

HBase のインスタンスを停止するには、停止スクリプトを実行します。

$ ./bin/stop-hbase.sh
stopping hbase...............

1.2.5. 次は

ここで説明したスタンドアロンモードでのセットアップが適しているのは、テストや試験を行う場合だけです。次の「通常のスタートガイド」では、スタンドアロン以外の HBase の実行モードについて詳しく取り上げ、分散 HBase をデプロイするのに必要なものや重要な設定について説明し ます。

1.3. 通常のスタートガイド

1.3.1. 必要なもの

HBase を実行するには、以下に示すものが必要です。以下のセクションを注意深く読んで、必要なものをすべて用意してください。不足しているものがあると、奇妙なエラーが発生したり、データが失われることがあります。

1.3.1.1. java

Hadoop 同様、HBase では Oracle の java 6 が必要です。問題のある u18 を除いて、通常は利用可能な最新のバージョンを使うとよいでしょう (本書の執筆時点では u24 が最新バージョンです)。

1.3.1.2. hadoop

このバージョンの HBase は、Hadoop 0.20.x で動作します。Hadoop 0.21.x (および 0.22.x) では動作しません。永続的 sync のある HDFS 上で HBase を実行しないと、HBase のデータは失われます。現在、この永続的 sync の属性を備えているのは、branch-0.20-append ブランチだけです[1]。現在までこのブランチからの公式リリースは行われていないので、このブランチの指示を参考に自分で Hadoop をビルドする必要があります。この URL (branch-0.20-append) をチェックしてください。Hadoop のビルドの手順については、Hadoop の「How To Release」の記事の中ほどにある「Build Requirements」のセクションを参照してください。

あるいは、自分でビルドする代わりに Cloudera の CDH3 を使う方法もあります。CDH には、永続的 sync を追加するのに必要な 0.20-append パッチが含まれています (CDH3 ベータ、すなわち b2、b3、または b4 で十分です)。

HBase は Hadoop に依存しているので、HBase は lib ディレクトリ下に Hadoop jar のインスタンスをバンドルしています。このバンドルされている Hadoop は、該当する HBase のリリースの時点での Apache branch-0.20-append ブランチから作成されたものです。実際にクラスタ上で実行する Hadoop のバージョンが HBase のバージョンと一致していることが非常に重要です。バージョンミスマッチの問題を回避するために、HBase の lib ディレクトリにある hadoop jar ファイルを、実際にクラスタ上で実行する hadoop jar ファイルで置き換えてください。このとき、必ずクラスタ上のすべての jar を置き換えてください。バージョンミスマッチの問題とは、CDH では HDFS-724 への対応がなされていないのに対し、Hadoop の branch-0.20-append ブランチでは HDFS-724 への対応がなされているといった問題です。このパッチによって RPC バージョンが変わりますが、これはプロトコルが変更されたためです。バージョンミスマッチの問題はさまざまな現象となって表れますが、しばしばすべてがハングアップしたような状態になります。

Hadoop 0.20.2 の tarball に含まれている jar を、HBase に含まれている sync 対応の Hadoop jar で置き換えることはできますか?

置き換えてもかまいません。メーリングリストに投稿された最近のメッセージで、動作するとの報告があります。

Hadoop のセキュリティ

HBase は、Y! 0.20S や CDH3B3 など、Hadoop のセキュリティ機能を組み込んだ任意の Hadoop 0.20.x で動作します。ただしその場合、上で説明しているように、HBase に付属する Hadoop jar をセキュアなバージョンの Hadoop jar で置き換えてください。

1.3.1.3. ssh

リモート Hadoop デーモンとリモート HBase デーモンを管理する Hadoop スクリプトを使えるようにするために、ssh をインストールし、sshd を実行しておく必要があります。パスワードなしの ssh で、ローカルノードを含むすべてのノードにログインできなければなりません (Google で "ssh passwordless login" を検索してください)。

1.3.1.4. DNS

HBase はローカルのホスト名を使用して自身の IP アドレスを取得します。正引きと逆引きの両方の DNS 解決がきちんと行えるようになっている必要があります。

コンピュータに複数のインタフェースがある場合、HBase はプライマリホスト名の解決先となるインタフェースを使用します。

このような動作が条件に合わない場合には、hbase.regionserver.dns.interface を設定すれば、プライマリインタフェースを指定できます。この指定が機能するのは、クラスタの構成が一貫したものになっていて、すべてのホストが同じネットワークインタフェース設定になっている場合だけです。

別の方法として、システム全体のデフォルトとは異なるネームサーバーを選択するよう、hbase.regionserver.dns.nameserver を設定するやり方があります。

1.3.1.5. NTP

クラスタメンバーのクロックは基本的に合っている必要があります。いくらかのずれは許容されますが、ずれが激しい場合には動作がおかしくなることがあります。クラスタ上で NTP または同等のものを実行してください。

データの問い合わせで問題が生じたり、クラスタがおかしな動作をするような場合は、システム時間をチェックしてください。

1.3.1.6. ulimit

HBase はデータベースなので、同時に多くのファイルを使用します。*nix システムのデフォルトの ulimit -n である 1024 では不十分です。データを大量にロードすると、「FAQ: Why do I see "java.io.IOException...(Too many open files)" in my logs?」にあるとおり、ログに "java.io.IOException...(Too many open files)" と出力されます。また、次のようなエラーが出力されることもあります。

      2010-04-06 03:04:37,542 INFO org.apache.hadoop.hdfs.DFSClient: Exception increateBlockOutputStream java.io.EOFException
      2010-04-06 03:04:37,542 INFO org.apache.hadoop.hdfs.DFSClient: Abandoning block blk_-6935524980745310745_1391901
      

こうした問題を避けるために、ファイルデスクリプタの上限を変更します。10k 以上に設定してください。方法については、上に示した FAQ を参照してください。

正確を期して言うと、HBase プロセスを実行しているユーザーのファイルデスクリプタの上限の引き上げは、オペレーティングシステム側で設定することであって、HBase の設定ではありません。また、よくある勘違いとして、管理者はファイルデスクリプタの上限を引き上げたものの、そのユーザーとは別のユーザーで HBase が実行されるということがあります。HBase は、ulimit の値をログの先頭の行に出力します。この値が適切な値になっているかどうかを確認してください。[2]

1.3.1.6.1. Ubuntu での ulimit の設定

Ubuntu を使用している場合は、以下のように変更する必要があります。

ファイル /etc/security/limits.conf に次のような行を追加します。

hadoop  -       nofile  32768

上の hadoop は、実際に Hadoop と HBase を実行するユーザーで置き換えてください。それぞれを別のユーザーで実行する場合は、ユーザーごとに 1 つのエントリが必要です。

ファイル /etc/pam.d/common-session の最後の行として、次の行を追加します。

session required  pam_limits.so

この設定を行わないと、/etc/security/limits.conf に加えた変更は適用されません。

編集を終えたら、変更内容を有効にするために、必ずいったんログアウトしてからログインし直します。

1.3.1.7. dfs.datanode.max.xcievers

Hadoop HDFS DataNode には、一度にサービスを提供できるファイル数に上限があります。この上限を表すパラメータは xcievers です (ご推察のとおり、スペルは間違っています)。このパラメータについても、データのロードを行う前に、Hadoop の conf/hdfs-site.xmlxcievers の値を少なくとも次のように設定していることを確認してください。

      <property>
        <name>dfs.datanode.max.xcievers</name>
        <value>4096</value>
      </property>
      

設定を行ったら必ず HDFS を再起動してください。

上の設定を行わないと、奇妙なエラーが発生する可能性が高くなります。最終的には、xcievers を超えたことを警告するエントリが DataNode のログに出力されるようになりますが、その前兆として、ブロックが見つからないというメッセージが表示されます。たとえば次のようなメッセージです: 10/12/08 20:10:31 INFO hdfs.DFSClient: Could not obtain block blk_XXXXXXXXXXXXXXXXXXXXXX_YYYYYYYY from any node: java.io.IOException: No live nodes contain current block. Will get new block locations from namenode and retry...

1.3.1.8. Windows

HBase は Windows 上ではほとんどテストされていません。Windows 上で実働環境の HBase を実行することは推奨されません。

Windows 上で HBase を実行する場合は、*nix ライクな環境を用意してシェルスクリプトを使えるようにするために、Cygwin をインストールしなければなりません。詳細については、「Cygwin を使った Windows への HBase のインストール」を参照してください。また、Windows ユーザーが投稿した最新の対処方法についても、ユーザー向けメーリングリストで検索して参照してください。

1.3.2. HBase の実行モード: スタンドアロンモードと分散モード

HBase には、スタンドアロンモード分散モードの 2 つの実行モードがあります。デフォルトでは、HBase はスタンドアロンモードで実行されます。分散デプロイをセットアップするには、HBase の conf ディレクトリにある複数のファイルを編集して HBase の設定を行う必要があります。

どのモードで実行する場合も、conf/hbase-env.sh を編集し、使用する java を HBase に教えてやる必要があります。このファイルでは、JVM のヒープサイズやその他のオプション、ログファイルの場所など、HBase が参照する環境変数を設定します。JAVA_HOME には、インストールした java のルートを設定してください。

1.3.2.1. スタンドアロンモード

これは HBase のデフォルトの実行モードです。スタンドアロンモードについては、「クイックスタートガイド」で説明しています。スタンドアロンモードでは、HBase は HDFS の代わりにローカルファイルシステムを使用し、すべての HBase デーモンとローカル ZooKeeper を 1 つの JVM 内で実行します。ZooKeeper は既知のポートにバインドするので、クライアントは HBase にアクセスすることができます。

1.3.2.2. 分散モード

分散モードには、分散モードでありながらすべてのデーモンが単一のノードで実行される疑似分散モードと、デーモンがクラスタ内のすべてのノードに散らばって配置される完全分散モードがあります[3]

分散モードでは Hadoop Distributed File System (HDFS) のインスタンスが必要です。HDFS のセットアップ方法については、Hadoop の「必要なものと手順」を参照してください。先へ進む前に、適切に動作する HDFS が用意できていることを確認してください。

以下では、2 つの分散モードのセットアップ方法を説明します。疑似分散モード完全分散モードのどちらの場合も、インストールした HBase の起動、検証、および使用については、あとの「インストールした HBase の実行と動作確認」で説明しています。どちらのデプロイタイプについても、適用される検証スクリプトは同じです。

1.3.2.2.1. 疑似分散モード

疑似分散モードとは、1 台のホスト上で実行される分散モードのことです。HBase 上でのテストとプロトタイピングにはこのモードを使用してください。このモードは、実働環境や HBase のパフォーマンス評価には使用しないでください。

HDFS が正しくセットアップされていることを確認したら、conf/hbase-site.xml を編集します。このファイルには、「HBase のデフォルト設定」と「HDFS クライアント設定」に対するローカルなカスタマイズ設定や上書きする設定を追加します。hbase.rootdir プロパティを設定し、実行中の Hadoop HDFS インスタンスを指すようにします。このプロパティは、使用する Hadoop ファイルシステムのインスタンスを HBase に知らせます。たとえば、次のプロパティを hbase-site.xml に追加すると、NameNode がローカルマシン上のポート 9000 にある HDFS 上の /hbase ディレクトリを使う必要があることを、さらにレプリカを 1 つだけ実行する必要があること (疑似分散モードでの推奨設定) を HBase に教えることになります。

<configuration>
  ...
  <property>
    <name>hbase.rootdir</name>
    <value>hdfs://localhost:9000/hbase</value>
    <description>リージョンサーバーによって共有されるディレクトリ。
    </description>
  </property>
  <property>
    <name>dfs.replication</name>
    <value>1</value>
    <description>HLog および HFile ストレージのレプリケーション数。HDFS DataNode の数より多い値は指定できません。
    </description>
  </property>
  ...
</configuration>

注記

hbase.rootdir ディレクトリは、HBase に作成させるようにしてください。ディレクトリを HBase に作成させないと、「期待されるファイルがディレクトリに存在しないので移行作業 (マイグレーション) を行う必要があります」という内容の HBase の警告メッセージが表示されます (ディレクトリを HBase に作成させた場合、これらのファイルは HBase によって作成されます)。

注記

上の設定例では localhost にバインドしています。この場合、リモートクライアントからは接続することができません。リモートクライアントから接続する必要がある場合は、目的の構成に応じて設定を変更してください。

次は、疑似分散モードでインストールした HBase の実行と動作確認の方法について説明している「インストールした HBase の実行と動作確認」に進んでください。[4]

1.3.2.2.2. 完全分散モード

2 台以上のホスト上で HBase を完全分散モードで実行するには、ここで説明する設定を行ってください。まず、hbase-site.xml ファイルにプロパティ hbase.cluster.distributed を追加して値に true を設定し、hbase.rootdir に、HBase のデータの書き込み先となる適切な HDFS NameNode と場所を指定します。たとえば、NameNode が namenode.example.org のポート 9000 で実行されていて、HDFS 内の HBase のホームを /hbase にするには、次のように設定します。

<configuration>
  ...
  <property>
    <name>hbase.rootdir</name>
    <value>hdfs://namenode.example.org:9000/hbase</value>
    <description>リージョンサーバーによって共有されるディレクトリ。
    </description>
  </property>
  <property>
    <name>hbase.cluster.distributed</name>
    <value>true</value>
    <description>クラスタの実行モード。次のいずれかの値を指定します。
      false: スタンドアロンモードと疑似分散モードで、ZooKeeper を HBase が管理する場合。
      true: ZooKeeper クォーラムを HBase が管理しない完全分散モードの場合 (hbase-env.sh を参照)。
    </description>
  </property>
  ...
</configuration>
1.3.2.2.2.1. regionservers

完全分散モードの場合は、さらに conf/regionservers も修正する必要があります。regionservers ファイルには、HRegionServer を実行するすべてのホストを 1 行に 1 つずつ入力します (HBase の regionservers ファイルは、Hadoop の slaves ファイルに相当するファイルです)。このファイルに入力されているすべてのサーバーは、HBase クラスタの起動と停止時に、それに合わせて起動または停止されます。

1.3.2.2.2.2. ZooKeeper

分散モードの HBase は、実行中の ZooKeeper クラスタに依存しています。すべての参加ノードおよびクライアントが、実行中の ZooKeeper アンサンブルにアクセスできるようになっている必要があります。デフォルトでは、HBase がユーザーに代わって ZooKeeper "クラスタ" を管理します。具体的には、HBase の起動/停止プロセスの一環として、HBase が ZooKeeper アンサンブルの起動と停止を行います。このような方法とは別に、ZooKeeper アンサンブルを HBase と切り離して管理し、使用する ZooKeeper アンサンブルを HBase に教えてやるやり方もあります。ZooKeeper を HBase が管理するかどうかを指定するには、conf/hbase-env.shHBASE_MANAGES_ZK 変数を設定します。HBASE_MANAGES_ZK 変数のデフォルトの値は true で、HBase の起動/停止プロセスの一環として、HBase が ZooKeeper アンサンブルの起動/停止を行う設定になっています。

HBase が ZooKeeper アンサンブルを管理する場合、ZooKeeper の設定は ZooKeeper 本来の zoo.cfg ファイルで設定できます。また、もっと簡単な方法として、conf/hbase-site.xml で ZooKeeper のオプションを直接指定することもできます。ZooKeeper の設定オプションは、ZooKeeper のオプションの前にプリフィックスとして hbase.zookeeper.property を付けることで、HBase の hbase-site.xml XML 設定ファイルのプロパティとして設定できます。たとえば、ZooKeeper の clientPort の設定は、hbase.zookeeper.property.clientPort プロパティを設定することで変更できます。ZooKeeper の設定を含め、HBase によって使われるすべてのデフォルト値については、「HBase のデフォルト設定」のセクションを参照してください。ZooKeeper の設定については、このセクションの hbase.zookeeper.property プリフィックスが付いているプロパティに注目してください。[5]

少なくとも、ZooKeeper アンサンブルを構成するサーバーについては、hbase-site.xmlhbase.zookeeper.quorum プロパティを使って指定しておかなければなりません。このプロパティのデフォルト値は localhost の単一のアンサンブルメンバーになっており、完全分散モードの HBase で使うには不適切な設定です。(ローカルマシンだけにバインドするので、リモートクライアントからは接続することができません。)

ZooKeeper マシンは何台実行すればよいですか?

1 ノードだけの ZooKeeper アンサンブルを実行することもできますが、実働環境では 3、5、または 7 台のマシンから構成される ZooKeeper アンサンブルを実行することを推奨します。アンサンブルのメンバーが多ければ多いほど、ホストに障害が発生したときの耐性も高くなります。なお、マシンの台数は奇数にしてください。メンバー数が偶数の場合、クォーラム (定足数) を構成できなくなります。できれば各 ZooKeeper サーバーには約 1 GB の RAM を搭載し、ZooKeeper 専用のディスクを用意してください (専用のディスクを用意することが、ZooKeeper アンサンブルのパフォーマンスを高めるための最も確実な方法です)。非常に負荷の高いクラスタの場合、ZooKeeper サーバー群はリージョンサーバー群 (DataNode と TaskTracker) とは別のマシンで実行してください。

たとえば、ノード rs{1,2,3,4,5}.example.com のポート 2222 (デフォルトは 2181 です) にバインドされている ZooKeeper クォーラムを HBase に管理させるには、conf/hbase-env.shHBASE_MANAGE_ZK の設定を行っている行がコメントアウトされているか、そうでない場合には true が設定されていることを確認し、さらに conf/hbase-site.xml を編集して、hbase.zookeeper.property.clientPorthbase.zookeeper.quorum を適切に設定します。また、hbase.zookeeper.property.dataDir をデフォルト以外の場所にする必要もあります。デフォルトでは、ZooKeeper の永続データは /tmp 以下に置かれますが、このディレクトリの内容はしばしばシステムの再起動時に消去されるからです。次に示す設定例では、ZooKeeper の永続データを /usr/local/zookeeper に置くようにしています。

  <configuration>
    ...
    <property>
      <name>hbase.zookeeper.property.clientPort</name>
      <value>2222</value>
      <description>ZooKeeper の設定ファイル zoo.cfg のプロパティ。
      クライアントが接続するポートです。
      </description>
    </property>
    <property>
      <name>hbase.zookeeper.quorum</name>
      <value>rs1.example.com,rs2.example.com,rs3.example.com,rs4.example.com,rs5.example.com</value>
      <description>ZooKeeper クォーラムを構成するサーバーをカンマで区切って指定します。
      たとえば、「host1.mydomain.com,host2.mydomain.com,host3.mydomain.com」のように指定します。
      デフォルトでは、ローカルモードと疑似分散モードの場合、localhost に設定されています。
完全分散モードの場合には、ZooKeeper クォーラムを構成するサーバーをすべて指定する必要があります。
hbase-env.sh で HBASE_MANAGES_ZK が設定されている場合、このプロパティで指定されたサーバーが、HBase によって起動/停止されるサーバーになります。
      </description>
    </property>
    <property>
      <name>hbase.zookeeper.property.dataDir</name>
      <value>/usr/local/zookeeper</value>
      <description>ZooKeeper の設定ファイル zoo.cfg のプロパティ。
      スナップショットを格納するディレクトリを指定します。
      </description>
    </property>
    ...
  </configuration>
1.3.2.2.2.2.1. 既存の ZooKeeper アンサンブルの使用

HBase が管理していない既存の ZooKeeper クラスタを使うには、conf/hbase-env.shHBASE_MANAGES_ZKfalse を設定します。

  ...
  # Tell HBase whether it should manage it's own instance of Zookeeper or not.
  export HBASE_MANAGES_ZK=false

次に、アンサンブルの場所とクライアントポート (標準以外のポートを使う場合) を hbase-site.xml で設定するか、または適切に設定した zoo.cfg を HBase の CLASSPATH に追加します。HBase は、hbase-site.xml の設定よりも zoo.cfg の設定を優先します。

ZooKeeper を HBase が管理する場合、HBase は自身の通常の起動/停止プロセスの一環として、ZooKeeper サーバーの起動と停止を行います。HBase の起動/停止とは切り離して ZooKeeper をユーザー自身で実行する場合は、次の操作を行います。

${HBASE_HOME}/bin/hbase-daemons.sh {start,stop} zookeeper

この方法を使えば、HBase とは関係なく、ZooKeeper クラスタを HBase から起動できることに注意してください。HBase が再起動する場合も ZooKeeper を実行したままにして、HBase のシャットダウン時に一緒に ZooKeeper が停止しないようにするには、HBASE_MANAGES_ZK に必ず false を設定しておきます。

HBase とは独立して ZooKeeper クラスタを実行する方法の詳細については、「ZooKeeper スタートガイド」を参照してください。

1.3.2.2.2.3. HDFS クライアントの設定

Hadoop クラスタ上で HDFS クライアントの設定を行っている場合、すなわちサーバー側の設定とは別に、HDFS クライアントに使わせる設定がある場合は、次のいずれかの操作を行わない限り、このような設定は HBase からは認識されません。

  • hbase-env.sh の中で、HADOOP_CONF_DIR へのポインタを HBASE_CLASSPATH 環境変数に追加する。

  • hdfs-site.xml (または hadoop-site.xml) のコピー、あるいはより適切な方法として、これらのファイルへのシンボリックリンクを ${HBASE_HOME}/conf に追加する。

  • HDFS クライアントの設定がごく小量の場合には、それらの設定を hbase-site.xml に追加する。

このような HDFS クライアントの設定のひとつに dfs.replication があります。たとえば、レプリケーション数を 5 で実行したい場合でも、上のいずれかの操作を行って、HBase から設定を読み取ることができるようにしない限り、HBase はデフォルトのレプリケーション数である 3 でファイルを作成します。

1.3.2.3. インストールした HBase の実行と動作確認

まず、HDFS が実行されていることを確認します。HADOOP_HOME ディレクトリで bin/start-dfs.sh を実行して Hadoop HDFS デーモンを起動します。HDFS が適切に起動したかどうかは、Hadoop ファイルシステムに対して putget を行うことで確認できます。通常、HBase は MapReduce デーモンを使用しません。これらのデーモンは起動する必要はありません。

ZooKeeper を HBase に管理させずに自分で管理している場合は、ZooKeeper を起動し、実行されていることを確認します。それ以外の場合は、HBase が自身の起動プロセスの一環として、ユーザーに代わって ZooKeeper を起動します。

次のコマンドを実行して HBase を起動します。

bin/start-hbase.sh
HBASE_HOME ディレクトリで上のコマンドを実行します。

これで、HBase のインスタンスが実行中になります。HBase のログは logs サブディレクトリにあります。HBase の起動時に問題があったら、ログを参照してください。

HBase は、重要な属性を表示するためのユーザーインタフェースも起動します。このユーザーインタフェースは、デフォルトでは Master ホストのポート 60010 にデプロイされます (HBase リージョンサーバーはデフォルトではポート 60020 でリスンし、情報表示用の HTTP サーバーをポート 60030 で起動します)。Master が master.example.org という名前のホストのデフォルトポートで実行されている場合、この Master のホームページを表示するには、ブラウザで http://master.example.org:60010 にアクセスします。

HBase 起動後のテーブルの作成、データの追加、挿入したデータのスキャン、テーブルの無効化と削除の方法については、「Shell による操作」を参照してください。

HBase Shell の終了後に HBase を停止するには、次のコマンドを入力します。

$ ./bin/stop-hbase.sh
stopping hbase...............

場合によっては、HBase がシャットダウンするまでにある程度時間がかかります。クラスタを構成するマシンの数が多いと、それだけ時間も余計にかかります。分散モードで HBase を実行している場合は、HBase が完全にシャットダウンするまで待ってから Hadoop デーモンを停止してください。

1.3.3. 設定例

1.3.3.1. 分散モードで実行する HBase の基本設定

10 ノードのクラスタを使って分散モードで実行する HBase の基本設定の例を示します。この例では、ノードの名前は example0example1、...、のようになっており、example9 までのノードがあります。HBase Master と HDFS NameNode はノード example0 で実行します。リージョンサーバーは、ノード example1example9 で実行します。ZooKeeper アンサンブルは 3 つのノードで構成し、これを example1example2、および example3 のデフォルトポートで実行します。ZooKeeper のデータは、ディレクトリ /export/zookeeper に永続化します。このような例の場合、HBase conf ディレクトリにある主要設定ファイル、すなわち hbase-site.xmlregionservers、および hbase-env.sh の内容は次のようになります。

1.3.3.1.1. hbase-site.xml

<?xml version="1.0"?>
<?xml-stylesheet type="text/xsl" href="configuration.xsl"?>
<configuration>
  <property>
    <name>hbase.zookeeper.quorum</name>
    <value>example1,example2,example3</value>
    <description>ZooKeeper クォーラムを構成するサーバーをカンマで区切って指定します。
    </description>
  </property>
  <property>
    <name>hbase.zookeeper.property.dataDir</name>
    <value>/export/zookeeper</value>
    <description>ZooKeeper の設定ファイル zoo.cfg のプロパティ。
    スナップショットを格納するディレクトリを指定します。
    </description>
  </property>
  <property>
    <name>hbase.rootdir</name>
    <value>hdfs://example0:9000/hbase</value>
    <description>リージョンサーバーによって共有されるディレクトリ。
    </description>
  </property>
  <property>
    <name>hbase.cluster.distributed</name>
    <value>true</value>
    <description>クラスタの実行モード。次のいずれかの値を指定します。
      false: スタンドアロンモードと疑似分散モードで、ZooKeeper を HBase が管理する場合。
      true: ZooKeeper クォーラムを HBase が管理しない完全分散モードの場合 (hbase-env.sh を参照)。
    </description>
  </property>
</configuration>

    
1.3.3.1.2. regionservers

このファイルには、リージョンサーバーを実行するすべてのノードを記述します。現在の例では、HBase Master と HDFS NameNode を実行する最初のノード example0 を除くすべてのノードでリージョンサーバーを実行するので、ファイルの内容は次のようになります。

    example1
    example3
    example4
    example5
    example6
    example7
    example8
    example9
    
1.3.3.1.3. hbase-env.sh

以下に示すのは、hbase-env.sh ファイルとの違いを diff を使って出力したものです。HBase のヒープサイズをデフォルトの 1GB から変更し、4GB に設定しています。

    
$ git diff hbase-env.sh
diff --git a/conf/hbase-env.sh b/conf/hbase-env.sh
index e70ebc6..96f8c27 100644
--- a/conf/hbase-env.sh
+++ b/conf/hbase-env.sh
@@ -31,7 +31,7 @@ export JAVA_HOME=/usr/lib//jvm/java-6-sun/
 # export HBASE_CLASSPATH=
 
 # The maximum amount of heap to use, in MB. Default is 1000.
-# export HBASE_HEAPSIZE=1000
+export HBASE_HEAPSIZE=4096
 
 # Extra Java runtime options.
 # Below are what we set by default.  May only work with SUN JVM.

    

クラスタを構成するすべてのノードに conf ディレクトリの内容をコピーするには、rsync を使用します。



[1] 関連パッチの一覧については、branch-0.20-append の CHANGES.txt を参照してください。

[2] Hadoop クラスタの設定に役立つ有益な情報源として Aaron Kimballs の「Configuration Parameters: What can you just ignore?」があるので、参照してください。

[3] 疑似分散モードと完全分散モードという用語は Hadoop に由来しています。

[4] 疑似分散モードで実行するときに追加の Master とリージョンサーバーを起動する方法については、「疑似分散モードでの HBase の実行」を参照してください。

[5] ZooKeeper の設定の完全な一覧については、ZooKeeper の zoo.cfg を参照してください。HBase には zoo.cfg は含まれていないので、適切な ZooKeeper をダウンロードして、その中の conf ディレクトリを探す必要があります。

第2章 アップグレード

すでに説明した「必要なもの」、特に Hadoop のバージョンに関する部分をよく読んでください。

2.1. HBase 0.20.x または 0.89.x から HBase 0.90.x へのアップグレード

このバージョンの 0.90.x HBase は、HBase 0.20.x または HBase 0.89.x によって書き込まれたデータに対しても動作させることができます。移行のための手順は必要ありません。HBase 0.89.x および HBase 0.90.x はリージョンディレクトリの名前をそれまでとは異なる方法で書き出します。具体的には、jenkins ハッシュの代わりにリージョン名の md5 ハッシュを使ってリージョンディレクトリに名前を付けます。そのため、いったん HBase 0.89.x または HBase 0.90.x を起動すると、HBase 0.20.x に戻ることはできなくなります。

アップグレードするときは、必ず conf ディレクトリから hbase-default.xml を削除してください。0.20.x バージョンのこのファイルには、0.90.x HBase では必ずしも最適とはいえない設定が含まれています。hbase-default.xml ファイルは現在は HBase jar にバンドルされており、ファイルはここから読み取られます。このファイルの内容を調べたいときは、ソースツリーの src/main/resources/hbase-default.xml にあるファイルか、または「HBase のデフォルト設定」を参照してください。。

最後の注意点として、0.20.x からアップグレードする場合は、シェルで .META. スキーマをチェックしてください。HBase を実行する際の MEMSTORE_FLUSHSIZE の従来の推奨値は 16KB です。シェルで hbase> scan '-ROOT-' を実行してください。これで現在の .META. スキーマが表示されます。MEMSTORE_FLUSHSIZE のサイズをチェックします。サイズは 16KB (16384) ですか? もしそうなら、値を変更する必要があります ('通常' ないしデフォルトの値は 64MB (67108864) です)。スクリプト bin/set_meta_memstore_size.rb を実行してください。これで、.META. スキーマに対して必要な変更が加えられます。この変更を行わないと、クラスタの動作が遅くなる可能性があります[6]

第3章 設定

HBase は、Hadoop と同じ設定システムを使っています。デプロイの設定を行うには、環境変数を収めたファイル conf/hbase-env.sh を編集し (このファイルの設定の大部分は、クラスタを起動するためのランチャーシェルスクリプトで使われます)、次に、HBase のデフォルトを上書きする設定をはじめ、使用するファイルシステムや ZooKeeper アンサンブルの場所を HBase に教えるための設定などを XML ファイルに追加します[7]

HBase を分散モードで実行する場合は、HBase の設定を編集した後、クラスタを構成するすべてのノードに conf ディレクトリの内容をコピーする必要があります。HBase がユーザーに代わってこの処理を行うことはありません。rsync を使ってください。

3.1. hbase-site.xmlhbase-default.xml

Hadoop では、サイト固有の HDFS 設定は hdfs-site.xml ファイルに追加しますが、HBase でもまったく同様に、サイト固有のカスタマイズ設定は conf/hbase-site.xml ファイルに追加します。設定可能なプロパティについては、以下の「HBase のデフォルト設定」、または HBase ソースコードの src/main/resources ディレクトリにあるソースファイル hbase-default.xml を参照してください。

設定オプションのすべてが hbase-default.xml に記述されているわけではありません。変更することは稀と思われる設定については、コードだけに存在しています。このような設定を有効にする方法は、ソースコード自体を読んで該当する設定をファイルに記述する以外にありません。

現在のところ、設定ファイルに対する変更内容を HBase に反映させるには、クラスタを再起動する必要があります。

3.1.1. HBase のデフォルト設定

HBase のデフォルト設定

以下のドキュメントは、HBase のデフォルト設定ファイル hbase-default.xml をソースとして生成されています。

hbase.rootdir

リージョンサーバーによって共有され、HBase が永続データを書き込むディレクトリ。 URL は、ファイルシステムスキームを含んだ「完全修飾」URL である必要があります。たとえば、HDFS インスタンスの NameNode が namenode.example.org のポート 9000 で実行されていて、書き込み先の HDFS ディレクトリを '/hbase' にする場合は、hdfs://namenode.example.org:9000/hbase と指定します。デフォルトでは、HBase の書き込み先は /tmp です。デフォルトの設定を変更しないと、すべてのデータはマシンの再起動時に失われます。

デフォルト:file:///tmp/hbase-${user.name}/hbase

hbase.master.port

HBase Master のバインド先ポート。

デフォルト:60000

hbase.cluster.distributed

クラスタの実行モード。指定できる値は false か true のいずれかで、スタンドアロンモードの場合は false を、分散モードの場合は true を指定します。false を指定した場合、HBase はすべての HBase デーモンと ZooKeeper デーモンを 1 つの JVM 内で実行します。

デフォルト:false

hbase.tmp.dir

ローカルファイルシステム上の一時ディレクトリ。'/tmp' 以外のより永続性の高い場所を使用するには、この設定を変更します ('/tmp' ディレクトリの内容はしばしばシステムの再起動時に消去されます)。

デフォルト:/tmp/hbase-${user.name}

hbase.master.info.port

HBase Master の Web ユーザーインタフェースのポート。ユーザーインタフェースのインスタンスを実行しない場合は、-1 を設定します。

デフォルト:60010

hbase.master.info.bindAddress

HBase Master の Web ユーザーインタフェースのバインドアドレス。

デフォルト:0.0.0.0

hbase.client.write.buffer

HTable クライアント書き込みバッファのデフォルトサイズ (バイト単位)。バッファのサイズが大きければ大きいほど、消費されるメモリは (サーバーは渡された書き込みバッファをインスタンス化して処理するので、クライアントとサーバーのどちらでも) 増えますが、バッファのサイズが大きければ、実行される RPC の数もそれだけ減ります。サーバー側で消費するメモリのめやすは、hbase.client.write.buffer * hbase.regionserver.handler.count です。

デフォルト:2097152

hbase.regionserver.port

HBase リージョンサーバーのバインド先ポート。

デフォルト:60020

hbase.regionserver.info.port

HBase リージョンサーバーの Web ユーザーインタフェースのポート。リージョンサーバーのユーザーインタフェースを実行しない場合は、-1 を設定します。

デフォルト:60030

hbase.regionserver.info.port.auto

Master またはリージョンサーバーのユーザーインタフェースがバインド先ポートを探すようにするかどうかを指定します。hbase.regionserver.info.port がすでに使われている場合に、自動でポートを探すようにします。テスト時に有効にすると便利ですが、デフォルトでは無効です。

デフォルト:false

hbase.regionserver.info.bindAddress

HBase リージョンサーバーの Web ユーザーインタフェースのアドレス。

デフォルト:0.0.0.0

hbase.regionserver.class

使用するリージョンサーバーインタフェース。リモートリージョンサーバーへのプロキシを開くクライアントによって使われます。

デフォルト:org.apache.hadoop.hbase.ipc.HRegionInterface

hbase.client.pause

クライアントの一般的な一時停止の値。主に、get やリージョンの参照などが失敗したときに、再試行までどれだけ待機するかを示す値として使われます。

デフォルト:1000

hbase.client.retries.number

最大再試行回数。ルートリージョンサーバーからのルートリージョンの取得、セルの値の取得、行の更新の開始など、再試行可能なすべての操作の最大値として使われます。デフォルトは 10 回です。

デフォルト:10

hbase.client.scanner.caching

スキャナの next を呼び出した際、(ローカル、クライアント) メモリからデータが得られない場合に取得される行数。キャッシングの値を高くすればスキャナの動作は早くなりますが、メモリの消費は増え、キャッシュが空のときに next を何回か呼び出しすると、動作にかかる時間が長くなることがあります。1 つの呼び出しから次の呼び出しまでの時間が、スキャナのタイムアウト、すなわち hbase.regionserver.lease.period より大きくなるような設定は行わないでください。

デフォルト:1

hbase.client.keyvalue.maxsize

KeyValue インスタンスの合計最大許容サイズを指定します。この値によって、ストレージファイルに保存される単一のエントリの上限が定まります。これらのデータは分割できないので、データが大き過ぎるためにこれ以上リージョンを分割できない事態を回避するのに役立ちます。この値には最大リージョンサイズの分数を設定するのが賢明です。0 以下の値を設定すると、チェックは行われません。

デフォルト:10485760

hbase.regionserver.lease.period

HRegion サーバーのリース期間 (ミリ秒単位)。デフォルトは 60 秒です。クライアントがこの期間内に報告を行わない場合、クライアントは死んでいるものとみなされます。

デフォルト:60000

hbase.regionserver.handler.count

リージョンサーバーで起動される RPC サーバーインスタンスの数。このプロパティは、Master によってマスターハンドラの数としても使われます。デフォルトは 10 です。

デフォルト:10

hbase.regionserver.msginterval

リージョンサーバーから Master へのメッセージ間の間隔 (ミリ秒単位)。

デフォルト:3000

hbase.regionserver.flushlogentries

ここで指定された数のエントリが蓄積すると HLog を HDFS に sync します。デフォルトは 1 です。すべての HLog.hflush で値がチェックされます。

デフォルト:1

hbase.regionserver.optionallogflushinterval

ここで指定された期間が経過すると、sync をトリガするのに十分なエントリが蓄積していなくても、HLog を HDFS に sync します。デフォルトは 1 秒です。単位: ミリ秒。

デフォルト:1000

hbase.regionserver.regionSplitLimit

リージョン数を制限し、この値を超えたらリージョンの分割を行わないようにします。これはリージョン数のハードリミットではなく、一定の制限を超えた後にリージョンサーバーに分割を停止させるためのガイドラインとして機能します。デフォルトは MAX_INT に設定されており、分割をブロックしません。

デフォルト:2147483647

hbase.regionserver.logroll.period

編集回数によらずコミットログをローリングする間隔。

デフォルト:3600000

hbase.regionserver.hlog.reader.impl

HLog ファイルリーダーの実装。

デフォルト:org.apache.hadoop.hbase.regionserver.wal.SequenceFileLogReader

hbase.regionserver.hlog.writer.impl

HLog ファイルライターの実装。

デフォルト:org.apache.hadoop.hbase.regionserver.wal.SequenceFileLogWriter

hbase.regionserver.thread.splitcompactcheckfrequency

リージョンサーバーが分割/コンパクションのチェックを実行する頻度。

デフォルト:20000

hbase.regionserver.nbreservationblocks

OOME 時に解放し、適切なクリーンアップを行ってからサーバーを停止できるようにするためのメモリの予約ブロック数。

デフォルト:4

hbase.zookeeper.dns.interface

ZooKeeper サーバーが自身の IP アドレスを報告するときに使うネットワークインタフェース名。

デフォルト:default

hbase.zookeeper.dns.nameserver

ネームサーバー (DNS) のホスト名または IP アドレス。ZooKeeper サーバーは、このネームサーバーを使って、通信と表示のためにマスターによって使われるホスト名を決定します。

デフォルト:default

hbase.regionserver.dns.interface

リージョンサーバーが自身の IP アドレスを報告するときに使うネットワークインタフェース名。

デフォルト:default

hbase.regionserver.dns.nameserver

ネームサーバー (DNS) のホスト名または IP アドレス。リージョンサーバーは、このネームサーバーを使って、通信と表示のためにマスターによって使われるホスト名を決定します。

デフォルト:default

hbase.master.dns.interface

マスターが自身の IP アドレスを報告するときに使うネットワークインタフェース名。

デフォルト:default

hbase.master.dns.nameserver

ネームサーバー (DNS) のホスト名または IP アドレス。マスターは、このネームサーバーを使って、通信と表示のために使われるホスト名を決定します。

デフォルト:default

hbase.balancer.period

Master でリージョンバランサを実行する間隔。

デフォルト:300000

hbase.regions.slop

いずれかのリージョンサーバーの持つリージョンが average + (average * slop) を超えた場合にリバランスを行います。デフォルトは 20% です。

デフォルト:0.2

hbase.master.logcleaner.ttl

HLog が .oldlogdir ディレクトリにとどまることができる最大時間。この時間を過ぎると、HLog は Master スレッドによって消去されます。

デフォルト:600000

hbase.master.logcleaner.plugins

LogsCleaner によって呼び出される LogCleanerDelegate のリストをカンマで区切って指定します。WAL/HLog クリーナーは指定された順に呼び出されるので、最も多くの HLog ファイルを削除する HLog クリーナーを先に記述します。独自の LogCleanerDelegate を実装するには、そのクリーナーを HBase のクラスパスに入れ、完全修飾クラス名をこのプロパティに追加します。デフォルトの 3 つのログクリーナーは必ずリストに追加してください。

デフォルト:org.apache.hadoop.hbase.master.TimeToLiveLogCleaner

hbase.regionserver.global.memstore.upperLimit

1 つのリージョンサーバー内のすべての MemStore の最大サイズ。このサイズを超えると、新しい更新はブロックされ、強制的にフラッシュが行われます。デフォルトはヒープの 40% です。

デフォルト:0.4

hbase.regionserver.global.memstore.lowerLimit

メモリに空きを作るために MemStore が強制的にフラッシュされる際、ここで指定された値に達するまでフラッシュ操作が続けられます。デフォルトはヒープの 35% です。この値が hbase.regionserver.global.memstore.upperLimit と等しいと、MemStore の制限によって更新がブロックされたときに発生するフラッシュの回数は最低限になります。

デフォルト:0.35

hbase.server.thread.wakefrequency

行う作業があるかどうか探す処理までのスリープ時間 (ミリ秒単位)。ログローラーなどのサービススレッドによって、スリープ間隔として使われます。

デフォルト:10000

hbase.hregion.memstore.flush.size

サイズがここで指定されたバイト数を超えた MemStore はディスクにフラッシュされます。この値は、hbase.server.thread.wakefrequency ごとに実行されるスレッドによってチェックされます。

デフォルト:67108864

hbase.hregion.preclose.flush.size

クローズ前のあるリージョンの MemStore がこのサイズ以上の場合、"pre-flush" を実行して MemStore を空にしてから、当該リージョンにクローズフラグを立てて、リージョンをオフラインにします。クローズ時には、クローズフラグの下でフラッシュが実行されてメモリが空にされます。この処理中、リージョンはオフラインとなり、書き込みは行われなくなります。MemStore の内容が大きい場合、このフラッシュ処理が完了するまで長い時間がかかることがあります。"pre-flush" は、MemStore の大部分を空にしてからクローズフラグを立ててリージョンをオフラインにすることで、クローズフラグの下で実行されるフラッシュ処理が行う作業をほとんどなくすことを意図したものです。

デフォルト:5242880

hbase.hregion.memstore.block.multiplier

MemStore が hbase.hregion.flush.size に hbase.hregion.block.memstore を乗じたバイトになった場合、更新をブロックします。更新トラフィックの急増中に、MemStore の無駄づかいを防ぐのに役立ちます。上限がないと、MemStore がいっぱいに満たされるため、結果が収められるファイルをフラッシュするときに、コンパクションや分割の実行に長い時間がかかったり、それ以上に悪い状態として、OOME が発生することがあります。

デフォルト:2

hbase.hregion.memstore.mslab.enabled

書き込み負荷が高い状況下でヒープのフラグメンテーションを防ぐための機能である MemStore-Local Allocation Buffer を有効にします。この機能により、ヒープの大きいシステムにおいて、すべてが止まったかのような状態になるガベージコレクションによる一時停止の頻度を抑えることができます。

デフォルト:true

hbase.hregion.max.filesize

HStoreFile の最大サイズ。列ファミリの HStoreFile のいずれか 1 つが、ここで指定された値を超えた場合、その部分をホスティングしている HRegion は 2 つに分割されます。デフォルトは 256MB です。

デフォルト:268435456

hbase.hstore.compactionThreshold

HStore のいずれか 1 つに含まれる HStoreFile の数がここで指定された値を超えた場合 (1 回の MemStore のフラッシュで 1 つの HStoreFile が書き出されます)、コンパクションが実行され、すべての HStoreFile ファイルが 1 つのファイルに書き換えられます。 値を大きくすればコンパクションの実行を遅らせることができますが、コンパクションが実行されると、完了までにかかる時間は増えます。

デフォルト:3

hbase.hstore.blockingStoreFiles

HStore のいずれか 1 つに含まれる HStoreFile の数がここで指定された値を超えた場合 (1 回の MemStore のフラッシュで 1 つの HStoreFile が書き出されます)、該当する HRegion に対する更新は、コンパクションが実行されるか、または hbase.hstore.blockingWaitTime が経過するまで、ブロックされます。

デフォルト:7

hbase.hstore.blockingWaitTime

hbase.hstore.blockingStoreFiles で定義された StoreFile の制限に達した後に HRegion が更新をブロックする時間。この時間が経過すると、たとえコンパクションが完了していない場合でも、HRegion は更新のブロックを中止します。デフォルトは 90 秒です。

デフォルト:90000

hbase.hstore.compaction.max

1 回の「マイナー」コンパクションでコンパクションする HStoreFile の最大数。

デフォルト:10

hbase.hregion.majorcompaction

あるリージョン内のすべての HStoreFile を対象とする「メジャー」コンパクションの間隔 (ミリ秒単位)。デフォルトは 1 日です。メジャーコンパクションの自動実行を無効にするには 0 を指定します。

デフォルト:86400000

hbase.mapreduce.hfileoutputformat.blocksize

mapreduce HFileOutputFormat は StoreFile/HFile を書き出します。この値は、書き出す HFile の最小ブロックサイズです。通常、HBase で HFile を書き出すときは、テーブルスキーマ (HColumnDescriptor) からブロックサイズを取得しますが、mapreduce OutputFormat のコンテキストでは、スキーマにアクセスすることができないので、ブロックサイズを設定ファイルから取得します。ブロックサイズを小さくすればするほど、インデックスは大きくなり、ランダムアクセスで取得できるデータは少なくなります。セルが小さく、個々のセルに高速にランダムアクセスしたい場合は、ブロックサイズに小さい値を設定してください。

デフォルト:65536

hfile.block.cache.size

HFile/StoreFile によって使われるブロックキャッシュに最大ヒープ (-Xmx 設定) のどれだけを割り当てるかを指定します (パーセント単位)。デフォルトは 0.2 で、20% を割り当てます。無効にするには 0 を指定します。

デフォルト:0.2

hbase.hash.type

HashFunction で使用するハッシュアルゴリズム。murmur (MurmurHash) と jenkins (JenkinsHash) の 2 つの値がサポートされています。ブルームフィルタによって使われます。

デフォルト:murmur

hbase.rpc.engine

クライアント/サーバー RPC 呼び出しの整列化に使う org.apache.hadoop.hbase.ipc.RpcEngine の実装。

デフォルト:org.apache.hadoop.hbase.ipc.WritableRpcEngine

hbase.master.keytab.file

構成済みの HMaster サーバー主体にログインするのに使う kerberos keytab ファイルへのフルパス。

デフォルト:

hbase.master.kerberos.principal

たとえば、"hbase/_HOST@EXAMPLE.COM"。HMaster プロセスを実行するために使う必要がある kerberos 主体名。主体名は user/hostname@DOMAIN 形式である必要があります。ホスト名部分に "_HOST" が使われている場合、これは実行中のインスタンスの実際のホスト名に置き換えられます。

デフォルト:

hbase.regionserver.keytab.file

構成済みの HRegionServer サーバー主体にログインするのに使う kerberos keytab ファイルへのフルパス。

デフォルト:

hbase.regionserver.kerberos.principal

たとえば、"hbase/_HOST@EXAMPLE.COM"。HRegionServer プロセスを実行するために使う必要がある kerberos 主体名。主体名は user/hostname@DOMAIN 形式である必要があります。ホスト名部分に "_HOST" が使われている場合、これは実行中のインスタンスの実際のホスト名に置き換えられます。hbase.regionserver.keytab.file で指定されたファイルに、この主体のエントリが存在していなければなりません。

デフォルト:

zookeeper.session.timeout

ZooKeeper セッションタイムアウト。HBase はこの値をセッションの推奨最大時間として ZooKeeper クォーラムに渡します。http://hadoop.apache.org/zookeeper/docs/current/zookeeperProgrammers.html#ch_zkSessions (日本語: http://oss.infoscience.co.jp/hadoop/zookeeper/docs/current/zookeeperProgrammers.html#ch_zkSessions)「クライアントは要求されたタイムアウトを送信しますが、サーバーがレスポンスの中で返すのは、サーバーがクライアントに与えることができるタイムアウトです。」を参照してください。単位はミリ秒です。

デフォルト:180000

zookeeper.znode.parent

ZooKeeper における HBase のルート ZNode。相対パスで指定された HBase の ZooKeeper ファイルはすべて、このノードの下に置かれます。デフォルトでは、HBase の ZooKeeper ファイルパスはすべて相対パスで指定されるので、特に変更しない限り、これらのファイルはすべてこのプロパティで指定されたディレクトリの下に置かれます。

デフォルト:/hbase

zookeeper.znode.rootserver

ルートリージョンの場所を保持している ZNode へのパス。Master はこのパスに対して書き込みを行い、クライアントとリージョンサーバーはこのパスに対して読み取りを行います。相対パスが指定された場合、親フォルダは ${zookeeper.znode.parent} になります。したがって、デフォルトでは、ルートの場所は /hbase/root-region-server に格納されます。

デフォルト:root-region-server

hbase.coprocessor.region.classes

すべてのテーブルでデフォルトでロードされる Coprocessor をカンマで区切って指定します。これらのクラスは、すべてのオーバーライドコプロセッサメソッドで、指定された順に呼び出されます。独自の Coprocessor を実装した後、これを HBase のクラスパスに置き、その完全修飾名をここで指定します。HTableDescriptor を設定することで、コプロセッサをオンデマンドで呼び出すこともできます。

デフォルト:

hbase.coprocessor.master.classes

アクティブな HMaster プロセスでデフォルトでロードされる org.apache.hadoop.hbase.coprocessor.MasterObserver コプロセッサをカンマで区切って指定します。これらのクラスは、すべての実装されたコプロセッサメソッドで、指定された順に呼び出されます。独自の MasterObserver を実装した後、これを HBase のクラスパスに置き、その完全修飾名をここで指定します。

デフォルト:

hbase.zookeeper.quorum

ZooKeeper クォーラムを構成するサーバーをカンマで区切って指定します。たとえば、「host1.mydomain.com,host2.mydomain.com,host3.mydomain.com」のように指定します。 デフォルトでは、ローカルモードと疑似分散モードの場合、localhost に設定されています。 完全分散モードの場合には、ZooKeeper クォーラムを構成するサーバーをすべて指定する必要があります。 hbase-env.sh で HBASE_MANAGES_ZK が設定されている場合、このプロパティで指定されたサーバーが、HBase によって起動/停止されるサーバーになります。

デフォルト:localhost

hbase.zookeeper.peerport

ZooKeeper のピアが互いに通信するために使うポート。詳細については、http://hadoop.apache.org/zookeeper/docs/r3.1.1/zookeeperStarted.html#sc_RunningReplicatedZooKeeper (日本語: http://oss.infoscience.co.jp/hadoop/zookeeper/docs/current/zookeeperStarted.html#sc_RunningReplicatedZooKeeper) を参照してください。

デフォルト:2888

hbase.zookeeper.leaderport

ZooKeeper がリーダー選挙に使うポート。詳細については、http://hadoop.apache.org/zookeeper/docs/r3.1.1/zookeeperStarted.html#sc_RunningReplicatedZooKeeper (日本語: http://oss.infoscience.co.jp/hadoop/zookeeper/docs/current/zookeeperStarted.html#sc_RunningReplicatedZooKeeper) を参照してください。

デフォルト:3888

hbase.zookeeper.property.initLimit

ZooKeeper の設定ファイル zoo.cfg のプロパティ。最初の同期化フェーズに割り当てることができる時間 (tick 数)。

デフォルト:10

hbase.zookeeper.property.syncLimit

ZooKeeper の設定ファイル zoo.cfg のプロパティ。リクエストを送信してから確認を受け取るまでに経過可能な時間 (tick 数)。

デフォルト:5

hbase.zookeeper.property.dataDir

ZooKeeper の設定ファイル zoo.cfg のプロパティ。スナップショットを格納するディレクトリを指定します。

デフォルト:${hbase.tmp.dir}/zookeeper

hbase.zookeeper.property.clientPort

ZooKeeper の設定ファイル zoo.cfg のプロパティ。クライアントが接続するポートです。

デフォルト:2181

hbase.zookeeper.property.maxClientCnxns

ZooKeeper の設定ファイル zoo.cfg のプロパティ。IP アドレスによって識別される単一のクライアントが、ZooKeeper アンサンブルの単一のメンバーに対して行うことができる (ソケットレベルの) 同時接続数。スタンドアロンモードと疑似分散モードで ZooKeeper の接続に関する問題が生じるのを回避するには、値を高く設定してください。

デフォルト:30

hbase.rest.port

HBase REST サーバーのポート。

デフォルト:8080

hbase.rest.readonly

REST サーバーの起動モード。指定できる値は false か true のいずれかです。false の場合は、すべての HTTP メソッド、すなわち GET/PUT/POST/DELETE が許可されます。true の場合は、GET メソッドだけが許可されます。

デフォルト:false

hbase.defaults.for.version.skip

'hbase.defaults.for.version' チェックをスキップするには、値に true を設定します。maven によるプロジェクト生成以外の環境、たとえば IDE を実行している場合などは、この値に true を設定すると便利なことがあります。次のような RuntimException が出力されるのを回避するには、このブール値に true を設定します: "hbase-default.xml file seems to be for an old version of HBase (@@@VERSION@@@), this version is X.X.X-SNAPSHOT"。

デフォルト:false

3.2. hbase-env.sh

このファイルでは、HBase の環境変数を設定します。たとえば、ヒープサイズやガベージコレクタの設定など、HBase デーモンの起動時に JVM に渡すオプションを指定します。また、HBase の設定、ログディレクトリ、nice 値、ssh のオプション、プロセス識別子 (pid) ファイルを置く場所なども、このファイルで指定できます。conf/hbase-env.sh を開いて、ファイルの内容をよく読んでください。各オプションについてかなり詳しい説明があります。起動時に HBase デーモンに読み込ませたい設定がある場合は、ここで環境変数を設定してください。

設定ファイルに対する変更内容を HBase に反映させるには、クラスタを再起動する必要があります。

3.3. log4j.properties

HBase のファイルをローリングする頻度や、HBase がメッセージを記録するときのログレベルを変更するには、このファイルを編集します。

このファイルを編集した後、変更内容を HBase に反映させるには、クラスタを再起動する必要があります。ただし、個々のデーモンのログレベルについては、HBase のユーザーインタフェースを使って変更することができます。

3.4. 重要な設定

ここでは、重要な設定について説明します。必要な設定と、ひととおり目を通しておくと役立つ推奨設定とに分けて説明します。

3.4.1. 必要な設定

必要なもの」を参照してください。このセクションでは、負荷のかかる HBase を実行するのに最小限必要となる 2 つの設定、すなわちファイルデスクリプタの ulimitdfs.datanode.max.xcievers の設定について説明しています。

3.4.2. 推奨設定

3.4.2.1. zookeeper.session.timeout

デフォルトのタイムアウトは 3 分 です (値は秒単位で指定します)。この設定では、サーバーがクラッシュした場合、Master がクラッシュに気付いて、回復を開始するまで 3 分かかります。それよりも早く Master が障害に気付くようにするには、このタイムアウトを 1 分またはそれよりも少ない値に設定します。この値を変更する前に、JVM ガベージコレクションの設定を適切に管理しているかどうか確認してください。そうでない場合、ガベージコレクションが ZooKeeper セッションタイムアウトよりも長い時間続くと、リージョンサーバーの機能が停止します (このこと自体は問題にならないかもしれません。リージョンサーバーがガベージコレクションを実行してから長時間が経過している場合は、サーバー側で回復操作を開始する方法もあるからです)。

このプロパティの設定を変更するには、hbase-site.xml を編集し、修正後のファイルをクラスタ全体にコピーして、クラスタを再起動します。

この値を高めに設定しているのは、大量のデータをインポートしている最中にリージョンサーバーがダウンするのはなぜですかという初心者の質問がメーリングリストによく投稿され、この質問に答える手間をあらかじめ省いておくためです。リージョンサーバーがダウンする主な原因は、JVM の調整が行われておらず、リージョンサーバーがガベージコレクションによって長時間一時停止状態になることにあります。開発チームとしては、ユーザーは徐々に HBase に慣れていくものだとはいえ、細かな点まですべて知らなくてもよいようにするべきだと考えます。HBase を使っている間にある程度自信がつけば、このプロパティのような設定も適切に行えるようになるはずです。

3.4.2.2. hbase.regionserver.handler.count

ユーザーテーブルに対する受信リクエストに応答するために、開いたままにしておくスレッドの数を指定します。デフォルトの 10 はかなり小さい値ですが、これは、並行クライアントの数が多く、大きな書き込みバッファを使用しているリージョンサーバーが、ユーザーによって kill されるのを防ぐためです。めやすとしては、リクエストあたりのペイロードが MB に近くなる場合 (大きなデータの put、大きなキャッシュを使ったスキャン) には値を小さく、ペイロードが小さい場合 (get、小さなデータの put、ICV、delete) の場合には値を大きくします。

接続するクライアントのペイロードが小さい場合には、クライアントの最大数に設定するのが安全です。典型的な例として、ウェブサイトにサービスを提供するクラスタを挙げることができます。このようなクラスタでは、一般に put はバッファリングされず、ほとんどの操作は get だからです。

この設定に大きな値を指定すると危険なのはなぜかというと、あるリージョンサーバーで現在行われているすべての put の合計サイズが、そのリージョンサーバーのメモリを過度に圧迫し、場合によっては OutOfMemoryError を発生させる可能性があるからです。少ないメモリで稼働しているリージョンサーバーは、JVM のガベージコレクタの実行をそれだけ頻繁にトリガすることになり、いずれは GC による一時停止がはっきりとわかるほどになります (その理由は、ガベージコレクタがどれだけ懸命に処理を行ったとしても、すべてのリクエストのペイロードを保持するのに使われているメモリ全体は破棄することができないからです)。それから一定の時間が経過すると、クラスタ全体のスループットが影響を受けます。これは、問題のリージョンサーバーにヒットするリクエストの処理に時間が余計かかるようになって、そのことが事態をさらに悪化させるからです。

3.4.2.3. 大容量のメモリを搭載したマシンのための設定

HBase は、ユーザーがテストに使用するほとんどあらゆる種類のマシンで動作するよう、十分に余裕をとった妥当な構成でリリースされています。ただし、大容量のメモリを搭載したマシンを使う場合 (HBase に 8GB 以上のヒープがある場合)、以下の構成オプションが役立つことがあります。[準備中]。

3.4.2.4. LZO 圧縮

LZO 圧縮を有効にすることは十分に検討に値します。LZO 圧縮が処理に与える影響はほとんどなく、ほぼすべてのケースでパフォーマンスが向上します。

ただ残念なことに、HBase は Apache ライセンス、LZO は GPL というライセンスの問題があるので、LZO を HBase に同梱することはできません。したがって、HBase をインストールしてから LZO をインストールする必要があります。HBase で LZO を使う方法については、wiki の「Using LZO Compression」のページを参照してください。

LZO を使っているときに生じやすい問題として、クラスタの初期セットアップはスムーズにいくものの、1 か月が経過して、システム管理者がクラスタにマシンを 1 台追加しようとしたときに、新しいマシンで LZO のフィクスアップを行うのを忘れていて、そのために動作がおかしくなる、ということがあります。HBase 0.90.0 以降のバージョンでは、問題の原因が何かはっきりわかる形でエラーになるようにしていますが、必ずしもそうならない場合もあるかもしれません。そのときのために、ここで説明したことをちょっと頭の隅にとどめておいてください[8]

また、本書の最後の付録「HBase での圧縮」も参照してください。

3.4.2.5. リージョンのサイズを大きくする

クラスタ上のリージョンの総数を減らすために、リージョンのサイズを大きくすることを検討してください。一般に、管理するリージョンの数が少なければ少ないほど、クラスタの実行もスムーズになります (あるリージョンにアクセスが集中し、リクエストの負荷をクラスタ上で分散させたい場合には、あとからいつでも大きなリージョンを手動で分割することができます)。デフォルトでは、リージョンのサイズは 256MB です。このサイズを 1GB にして HBase を実行することもできます。もっと大きなリージョン、たとえば 4GB やそれ以上のサイズのリージョンで HBase を実行しているユーザーもいます。hbase-site.xmlhbase.hregion.max.filesize を調整してください。

3.4.2.6. 分割の管理

HBase にリージョンを自動分割させる代わりに、分割を手動で管理してください[9]。データの量が増大し続けると、分割が継続的に必要になります。手動分割では、どのようなリージョンがあるかを常に正確に把握しているので、自動分割の場合と比べると、長期的なデバッグやプロファイリングははるかに容易になります。リージョンが常に分割されて名前が変更される状況では、ログを追跡してリージョンレベルの問題を特定することは困難です。データをオフラインにする際のバグがあるうえに、分割されたリージョンの数が不明という状況は、決して好ましいものではありません。何らかのバグが原因で、HBase による HLog または StoreFile の処理が間違って行われず、1 日ほど経過してからそのことに気付いた場合でも、これらのファイルで指定されているリージョンは現在のリージョンと同じであると確実に判断することができ、データの回復/再生を行う際もそれほど悩まずに済みます。また、使用するコンパクションアルゴリズムを細かく調整することができます。データがほぼ画一的に増加するようなケースでは、すべてのリージョンがほとんど同時に同じデータサイズに達するので、分割/コンパクションストームが起こりやすくなります。手動分割を使えば、複数のメジャーコンパクションを交替で定期的に実行することにより、ネットワーク IO の負荷を分散させることができます。

では、どうすれば自動分割を無効にできるのでしょうか。自動分割が行われるかどうかは、設定値 hbase.hregion.max.filesize によって決まります。手動分割を忘れた場合のことを考えて、この値を Long.MAX_VALUE にしておくことは、推奨されません。推奨設定は 100GB で、このサイズに達すると 1 時間以上、メジャーコンパクションが行われることになります。

リージョンを作成する際に、あらかじめ分割しておくリージョンの最適な数はどれくらいでしょうか。これは、アプリケーションの用途によって異なります。あらかじめ分割しておくリージョンをサーバーあたり 10 くらいの低い値からスタートして、データが時間の経過とともにどのように増加していくかを監視するとよいでしょう。小さ過ぎるくらいのリージョンを設定しておいて、あとでローリング分割を実行する方がより好ましいと言えます。もう少し詳しく言えば、リージョンの数をどれくらいにしておくかを左右するのは、リージョン内でサイズの最も大きな StoreFile です。データサイズが増加すると、StoreFile は時間の経過とともに大きくなります。この場合、最も大きなリージョンのサイズを十分に大きく取り、Store に対するコンパクション選択アルゴリズムが、定期的なメジャーコンパクションのときだけに該当リージョンをコンパクションするようにしておきます。こうしておかないと、クラスタでコンパクションストームが起こりやすくなります。なぜなら、アルゴリズムの判定結果に基づいて、大量のリージョンに対して同時にメジャーコンパクションが実行されることになるからです。なお、コンパクションストームはデータの画一的な増加が原因であって、手動分割が原因ではないので、その点には注意してください。

リージョンを小さく分割し過ぎた場合は、HConstants.MAJOR_COMPACTION_PERIOD を設定することで、メジャーコンパクションの間隔を広げることができます。データサイズが大きくなり過ぎた場合は、(0.90.0 以降の HBase の) org.apache.hadoop.hbase.util.RegionSplitter スクリプトを使って、すべてのリージョンに対して、ネットワーク IO セーフなローリング分割を実行してください。

3.5. HBase クラスタに接続するクライアントおよびクライアントの依存関係

HBase Master は移動する可能性があるので、クライアントは ZooKeeper に現在の重要な場所についての情報を問い合わせてブートストラップします。ZooKeeper はこうした重要な場所の値のすべてを保持しています。したがって、クライアントは何よりもまず ZooKeeper アンサンブルの場所を知る必要があります。通常、ZooKeeper アンサンブルの場所は hbase-site.xml に保持されており、クライアントは CLASSPATH からこのファイルを探します。

IDE から HBase クライアントを実行するように構成している場合は、クラスパスに conf/ ディレクトリを含め、クライアントが hbase-site.xml の設定を見つけることができるように (または、src/test/resources を追加して、テストで使われる hbase-site.xml を読み取ることができるように) する必要があります。

HBase のクライアントがクラスタに接続するうえで最低限必要なことは、hbase、hadoop、log4j、commons-logging、commons-lang、および zookeeper の各 jar が CLASSPATH にあることです。

次に示すのは、クライアントとしてのみ動作する場合の hbase-site.xml の基本設定の例です。

<?xml version="1.0"?>
<?xml-stylesheet type="text/xsl" href="configuration.xsl"?>
<configuration>
  <property>
    <name>hbase.zookeeper.quorum</name>
    <value>example1,example2,example3</value>
    <description>ZooKeeper クォーラムを構成するサーバーをカンマで区切って指定します。
    </description>
  </property>
</configuration>

3.5.1. Java クライアントの設定

Java が hbase-site.xml の内容を読み取る方法

Java クライアントが使う設定は、HBaseConfiguration のインスタンスに保持されています。HBaseConfiguration のファクトリメソッド HBaseConfiguration.create(); が呼び出されると、このメソッドはクライアントの CLASSPATH で見つかった最初の hbase-site.xml の内容 (このファイルがある場合) を読み取ります (このメソッドが呼び出されると、見つかった任意の hbase-default.xml も読み取られます。hbase-default.xmlhbase.X.X.X.jar に同梱されています)。設定を直接指定して、hbase-site.xml の読み取りを不要にすることもできます。たとえば、クラスタで使う zookeeper アンサンブルをプログラムで設定するには、次のようにします。

Configuration config = HBaseConfiguration.create();
config.set("hbase.zookeeper.quorum", "localhost");  // ローカルホストで実行している ZooKeeper を指定.

複数の zookeeper インスタンスによって ZooKeeper アンサンブルが構成されている場合、これらのインスタンスは (hbase-site.xml ファイルで指定するときと同様に) カンマで区切って指定することができます。このようにして値を設定した Configuration のインスタンスは、その後 HTable などに渡すことができます。



[7] XML ファイルの編集は慎重に行ってください。具体的には、すべての要素が閉じられていることを確認します。編集を終えたら、xmllint または同種のツールを使って、ドキュメントの形式が整っているかどうかチェックします。

[8] LZO のインストールのし忘れを防ぐ機能については、hbase.regionserver.codecs を参照してください。

[9] 以下の内容は、0.90.0 以降のリリースの HBase に追加された org.apache.hadoop.hbase.util.RegionSplitter ツールの最初の部分の javadoc から抜き出したものです。

第4章 HBase Shell

HBase Shell は、(J)Ruby の IRB にいくつか HBase 固有のコマンドを追加したものです。HBase Shell では、IRB でできることは何でもできるはずです。

HBase Shell を実行するには、次のようにします。

$ ./bin/hbase shell

help」と入力して <RETURN> キーを押し、シェルのコマンドとオプションの一覧を表示します。help コマンドの出力のうち、少なくとも最後のいくつかのパラグラフには目を通し、HBase Shell での変数やコマンドの引数の入力の方法、特にテーブル名、行、列などを引用符でどのように囲まなければならないかについて、しっかりと理解しておきましょう。

基本的なシェルの操作については、「Shell による操作」を参照してください。

4.1. スクリプトの実行

HBase でのスクリプト例は、HBase の bin ディレクトリにあります。最後が .rb で終わるファイルを参照してください。これらのファイルを実行するには、次のようにします。

$ ./bin/hbase org.jruby.Main PATH_TO_SCRIPT

4.2. Shell の使い方

4.2.1. irbrc

ホームディレクトリに自分用の .irbrc ファイルを作成します。カスタマイズした設定をこのファイルに追加します。たとえば、コマンドの履歴を残すようにすると、次回 Shell を呼び出したときも、入力したコマンドが保存されていて便利です。

                        $ more .irbrc
                        require 'irb/ext/save-history'
                        IRB.conf[:SAVE_HISTORY] = 100
                        IRB.conf[:HISTORY_FILE] = "#{ENV['HOME']}/.irb-save-history"

.irbrc に記述できるその他の設定については、ruby のドキュメントを参照してください。

4.2.2. LOG の日付からタイムスタンプへの変換

HBase のログの '08/08/16 20:56:29' という日付をタイムスタンプに変換するには、次のようにします。

                    hbase(main):021:0> import java.text.SimpleDateFormat
                    hbase(main):022:0> import java.text.ParsePosition
                    hbase(main):023:0> SimpleDateFormat.new("yy/MM/dd HH:mm:ss").parse("08/08/16 20:56:29", ParsePosition.new(0)).getTime() => 1218920189000

逆方向の変換を行うには、次のようにします。

                    hbase(main):021:0> import java.util.Date
                    hbase(main):022:0> Date.new(1218920189000).toString() => "Sat Aug 16 20:56:29 UTC 2008"

SimpleDateFormat に少し手を加えれば、HBase のログの書式と正確に同じ書式で出力することができます。

4.2.3. デバッグ

4.2.3.1. Shell のデバッグスイッチ

シェルでデバッグスイッチをセットすると、例外発生時にスタックトレースを通常より多く表示するなど、コマンドを実行したときの出力を増やすことができます。

hbase> debug <RETURN>

4.2.3.2. DEBUG ログレベル

シェルで DEBUG レベルのログを有効にするには、-d オプションを付けてシェルを起動します。

$ ./bin/hbase shell -d

第5章 HBase のビルド

5.1. Apache の Maven リポジトリへの HBase リリースの追加

Publishing Maven Artifacts」に書かれている指示に従ってください。すべてをうまく動作させるためのポイントは、maven release plugin からの質問に適切に答えること、実際のブランチを使っていることを確認すること、および、mvn release:perform のステップを実行する前に、(これが非常に重要な点ですが) 前のステップの release:perform によって ${HBASE_HOME} に置かれた release.properties ファイルを手作業で編集することです。このファイルを編集して、SVN 内の正しい場所を指すようにしてやる必要があります。

もし次のようなメッセージが表示されたら、pom.xml 内のバージョンを編集して、バージョンに -SNAPSHOT を付ける (およびコミットする) 必要があることを示しています。

[INFO] Scanning for projects...
[INFO] Searching repository for plugin with prefix: 'release'.
[INFO] ------------------------------------------------------------------------
[INFO] Building HBase
[INFO]    task-segment: [release:prepare] (aggregator-style)
[INFO] ------------------------------------------------------------------------
[INFO] [release:prepare {execution: default-cli}]
[INFO] ------------------------------------------------------------------------
[ERROR] BUILD FAILURE
[INFO] ------------------------------------------------------------------------
[INFO] You don't have a SNAPSHOT project in the reactor projects list.
[INFO] ------------------------------------------------------------------------
[INFO] For more information, run Maven with the -e switch
[INFO] ------------------------------------------------------------------------
[INFO] Total time: 3 seconds
[INFO] Finished at: Sat Mar 26 18:11:07 PDT 2011
[INFO] Final Memory: 35M/423M
[INFO] -----------------------------------------------------------------------

第6章 HBase と MapReduce

javadoc の「HBase と MapReduce」を参照してください。まずはそこからスタートしてください。以下に示すのは補足説明です。

6.1. デフォルトの HBase MapReduce スプリッタ

HBase テーブルを MapReduce ジョブに取り込むのに TableInputFormat が使われている場合、そのスプリッタはテーブルの各リージョンに対して 1 つの map タスクを作成します。したがって、テーブルに 100 のリージョンがある場合、Scan でどれだけの列ファミリが選択されているかにかかわらず、そのジョブでは 100 の map タスクが存在することになります。

6.2. HBase Input MapReduce の例

HBase を MapReduce のソースとして使うには、次のようにして TableMapReduceUtil を介してジョブを構成します。

Job job = ...;	
Scan scan = new Scan();
scan.setCaching(500);  // 1 が Scan のデフォルトですが、これは MapReduce ジョブでは不適切です.
scan.setCacheBlocks(false);  
// その他の scan 属性を設定します.
...
  
TableMapReduceUtil.initTableMapperJob(
  tableName,   		// 入力 HBase テーブル名
  scan,			// 列ファミリと属性を管理するための Scan インスタンス
  MyMapper.class,	// mapper
  Text.class,		// reducer キー 
  LongWritable.class,	// reducer 値
  job			// job インスタンス
  );

mapper インスタンスでは TableMapper を継承します。

public class MyMapper extends TableMapper<Text, LongWritable> {
public void map(ImmutableBytesWritable row, Result value, Context context) 
throws InterruptedException, IOException {
// Result インスタンスから行のデータを処理します.

6.3. 1 つの MapReduce ジョブでのほかの複数の HBase テーブルへのアクセス

現在のフレームワークでは、MapReduce ジョブへの入力にできるのは、1 つの HBase テーブルだけですが、Mapper の setup メソッドで HTable インスタンスを作成すれば、1 つの MapReduce ジョブの中で、参照テーブルなどとしてほかの複数の HBase テーブルにアクセスすることができます。

public class MyMapper extends TableMapper<Text, LongWritable> {
  private HTable myOtherTable;

  @Override
  public void setup(Context context) {
    myOtherTable = new HTable("myOtherTable");
  }

第7章 HBase とスキーマ設計

さまざまな非 RDBMS データストアのモデリングの長所と短所については、Ian Varleys のマスター論文『No Relation: The Mixed Blessings of Non-Relational Databases』がたいへん優れた概論になっています。 ぜひ読んでください。

7.1. スキーマの作成

HBase のスキーマは、HBase Shell を介して、または Java API の HBaseAdmin を使うことで作成、更新することができます。

7.2. 列ファミリの数について

HBase が現在うまく対処できるのはせいぜい 2、3 の列ファミリなので、スキーマ内の列ファミリの数は低く抑えてください。現時点ではフラッシュとコンパクションはリージョンベースで行われるため、1 つの列ファミリが大量にデータを保持していて、これがフラッシュされると、隣接するファミリが保持しているデータが少量でも、これら隣接するファミリも同様にフラッシュされます。現在、コンパクションは、1 つの列ファミリのファイル数によってトリガされます。サイズベースではありません。列ファミリの数が多いと、フラッシュとコンパクション操作によって、不必要に I/O 負荷が高まる可能性があります (この問題に対しては、フラッシュとコンパクションを列ファミリベースで動作させるようにすることで対処する必要があります)。

作成するスキーマでは、可能なら 1 つの列ファミリで済ませるようにしてください。2 番目、3 番目の列ファミリを作るのは、データアクセスが一般に列スコープである場合、すなわち、問い合わせの対象が一方の列ファミリか、もう一方の列ファミリかのいずれかであって、2 つの列ファミリに同時に問い合わせることはない場合に限ってください。

7.3. 単調増加する行キー/時系列データ

Tom White 著『Hadoop: The Definitive Guide (邦訳: Hadoop)』 (O'Reilly刊) の中の HBase の章には「最適化のための注意事項」というセクションがあり、集団的画一行動を生じさせるような状況、すなわちテーブルのリージョンの 1 つ (つまり単一のノード) を対象に、すべてのクライアントがいっせいに処理を行い、その後また別のリージョンに対しても同じように処理を行うような状況を生じさせないよう、注意を促しています。単調増加する行キー (すなわちタイムスタンプを使った行キー) では、このような現象が起こります。BigTable ライクなデータストアにおいて単調増加する行キーが問題になるのはなぜなのかについて、IKai Lan がマンガで説明した「monotonically increasing values are bad (単調増加する値はダメ)」を参照してください。単調増加する行キーによって引き起こされる単一リージョンへの処理の集中は、入力レコードをランダム化してソート順にならないようすることで軽減できますが、一般には行キーにタイムスタンプや連番 (1, 2, 3 など) を使わないようにすることが、回避策として最も優れています。

どうしても時系列データを HBase にアップロードする必要がある場合は、成功例である OpenTSDB を参考にするとよいでしょう。OpenTSDB のサイトには、OpenTSDB が HBase で使っているスキーマについて説明したページがあります。OpenTSDB でのキーのフォーマットは実質的には [metric_type][event_timestamp] となっていて、一見したところ、上に述べたタイムスタンプをキーとして使わないというアドバイスと矛盾するように思われます。しかし、タイムスタンプがキーの先頭にない点が異なっており、メトリックの種類が数十から数百 (ないしそれ以上) あることが設計上の前提になっています。そのため、入力データが絶えず流れてくる場合でも、メトリックの種類と組み合わされることで、Put はテーブルのリージョンのさまざまなポイントに分散されます。

7.4. 行と列のサイズを最小限に抑える

HBase では、値は常にその座標とともに運ばれます。つまり、セルの値がシステム内で受け渡されるときは、必ずその行、カラム名、タイムスタンプも一緒に受け渡されます。必ずです。行やカラム名が大きい場合、特にそれらがセルの値に比べて大きい場合には、いくつか興味深い現象に遭遇するおそれがあります。そうした現象の 1 つとして、HBASE-3551 の終わりの方で Marc Limotte が説明しているケースがあります (このケースについてはぜひ読んでみてください)。このケースでは、セルの値の座標が大きいために、ランダムアクセスを容易にする目的で HBase ストアファイル (HFile) に保持されたインデックスが、HBase に割り当てられた RAM の大部分を使い切ってしまう可能性が考えられます。Marc は自分のコメントの中で、ブロックサイズを大きくして、ストアファイルのインデックスに入力が行われる間隔を延ばすか、または行とカラムの名前がもっと小さくて済むように、テーブルのスキーマを修正することを対処策として勧めています。`

7.5. テーブルの作成: リージョンの事前作成

デフォルトでは、HBase のテーブルは最初はリージョン 1 つで作成されます。これは、バルクインポートを行う場合、そのリージョンが十分大きくなって分割され、クラスタ全体に散らばった状態になるまで、すべてのクライアントが同じリージョンに書き込みを行うことを意味します。バルクインポートのプロセスをスピードアップするための有益な方法は、事前に空のリージョンを複数作成しておくことです。ただし、リージョンの数が多過ぎるとパフォーマンスを大きく損なうので、作成するリージョンの数は控え目にしてください。次に示すのは、16進のキーを使ってリージョンを事前作成する例です (注: この例は、個々のアプリケーションのキーに応じて修正する必要があります)。

public static boolean createTable(HBaseAdmin admin, HTableDescriptor table, byte[][] splits)
throws IOException {
  try {
    admin.createTable( table, splits );
    return true;
  } catch (TableExistsException e) {
    logger.info("table " + table.getNameAsString() + " already exists");
    // すでにテーブルが存在する.
    return false;  
  }
}

public static byte[][] getHexSplits(String startKey, String endKey, int numRegions) {
  byte[][] splits = new byte[numRegions-1][];
  BigInteger lowestKey = new BigInteger(startKey, 16);
  BigInteger highestKey = new BigInteger(endKey, 16);
  BigInteger range = highestKey.subtract(lowestKey);
  BigInteger regionIncrement = range.divide(BigInteger.valueOf(numRegions));
  lowestKey = lowestKey.add(regionIncrement);
  for(int i=0; i < numRegions-1;i++) {
    BigInteger key = lowestKey.add(regionIncrement.multiply(BigInteger.valueOf(i)));
    byte[] b = String.format("%016x", key).getBytes();
    splits[i] = b;
  }
  return splits;
}

第8章 メトリクス

8.1. メトリクスのセットアップ

メトリクスについての解説およびメトリクスの発行を有効にする方法については、「メトリクス」を参照してください。

8.2. リージョンサーバーのメトリクス

8.2.1. hbase.regionserver.blockCacheCount

8.2.2. hbase.regionserver.blockCacheFree

8.2.3. hbase.regionserver.blockCacheHitRatio

8.2.4. hbase.regionserver.blockCacheSize

8.2.5. hbase.regionserver.fsReadLatency_avg_time

8.2.6. hbase.regionserver.fsReadLatency_num_ops

8.2.7. hbase.regionserver.fsSyncLatency_avg_time

8.2.8. hbase.regionserver.fsSyncLatency_num_ops

8.2.9. hbase.regionserver.fsWriteLatency_avg_time

8.2.10. hbase.regionserver.fsWriteLatency_num_ops

8.2.11. hbase.regionserver.memstoreSizeMB

8.2.12. hbase.regionserver.regions

8.2.13. hbase.regionserver.requests

8.2.14. hbase.regionserver.storeFileIndexSizeMB

8.2.15. hbase.regionserver.stores

第9章 クラスタレプリケーション

クラスタレプリケーション」を参照してください。

第10章 データモデル

簡単に言うと、アプリケーションはデータを HBase のテーブルに格納します。テーブルは、 (row) と (column: カラム) から構成されます。HBase ではすべての列はある特定の列ファミリに属しています。テーブルのセル (行と列の座標の交点) はバージョン管理されています。セルの内容は未解釈のバイト配列です。

テーブルの行キーもバイト配列なので、文字列から long 値のバイナリ表現や直列化データ構造まで、ほとんどあらゆるものを行キーとして使うことができます。HBase テーブルの行は、行キーでソートされています。ソートはバイト順です。すべてのテーブルアクセスは、テーブルの主キーである行キーを介して行われます。

10.1. テーブル

テーブルは、スキーマの定義時に宣言されます。

10.2. 行

行キーは未解釈のバイト配列です。行は辞書順にソートされ、最も低位のものがテーブル内で最初に出現します。テーブルの名前空間の始まりと終わりを示すのには、ともに空のバイト配列が使われます。

10.3. 列ファミリ

HBase では、列は列ファミリにグループ化されます。ある 1 つの列ファミリのすべての列メンバーは、共通のプリフィックスを持っています。たとえば、列 courses:history および列 courses:math は、いずれも courses 列ファミリのメンバーです。コロン文字 (:) は、列ファミリと列ファミリ修飾子を区切ります。列ファミリのプリフィックスは、印字可能文字から構成されていなければなりません。これに続く列ファミリを修飾する部分、すなわち列ファミリ修飾子 (qualifier) は、任意のバイトで構成することができます。列ファミリは、スキーマの定義時に宣言されなければならないのに対し、列はスキーマの定義時に定義しておく必要はなく、テーブルが起動して動作している最中に、その場で作成することができます。

物理的には、列ファミリのすべてのメンバーは、まとめて一緒にファイルシステムに格納されます。各種の調整やストレージの指定は列ファミリレベルで行われるため、アクセスパターンやサイズに関する一般的特徴については、列ファミリのすべてのメンバーで同じであることが望ましいといえます。

10.4. セル

{行, 列, バージョン} のタプルによって正確に特定されるのが、HBase のセルです。セルの内容は未解釈のバイト配列です。

10.5. バージョン

{行, 列, バージョン} のタプルによって正確に特定されるのが、HBase のセルです。行と列が同じで、バージョンの次元でのみセルのアドレスが違うセルは無数に存在することができます。

行と列のキーはバイト配列で表現されますが、バージョンは long 整数で指定されます。通常、この long 整数には、java.util.Date.getTime()System.currentTimeMillis() が返すもの、すなわち現在時刻と 1970 年 1 月 1 日 00:00:00 UTC との差などの時刻のインスタンスが格納されます。

HBase のバージョン次元は降順に格納されるため、ストアファイルから読み取りを行ったときに最初に見つかる値は最新の値になります。

HBase のセルのバージョンのセマンティクスについては、混乱しているユーザーも少なくないようです。なかでも、よく見かけるのは次のような質問です。

  • あるセルに対する複数の書き込みで同一のバージョンが指定されている場合、すべてのバージョンが保持されるのか、最後のバージョンだけが保持されるのか。[10]

  • 増加しないバージョン順でセルの書き込みを行うことはできますか。[11]

以下では、HBase のバージョンの次元がどのように機能するのかについて説明します[12]

10.5.1. バージョンと HBase での各種操作

ここでは、HBase の基本操作のそれぞれにおけるバージョンの次元のふるまいについて取り上げます。

10.5.1.1. Get/Scan

Get は Scan を土台にして実装されています。Get に関する以下の説明は、Scan にも等しくあてはまります。

デフォルト、すなわち get を行うときにバージョンを明示的に指定しなかった場合には、バージョンの値が最大のセルが返されます (これは最新の値である場合もあれば、そうでない場合もあります。この点については後述します)。デフォルトの動作は、次のように変更することができます。

  • 複数のバージョンを返すようにする (Get.setMaxVersions() を参照してください)。

  • 最新以外のバージョンを返すようにする (Get.setTimeRange() を参照してください)。

    与えられた値に等しいか、またはより小さい最新のバージョンを取得して、時間軸上の特定の 1 点における「最新」の状態のレコードを入手するには、範囲 (レンジ) に 0 から目的のバージョンまでを指定し、取得する最大バージョン数 (setMaxVersions) に 1 を指定します。

10.5.1.2. デフォルトの Get の例

次に示す Get では、目的の行の現在のバージョンだけを取得します。

        Get get = new Get(Bytes.toBytes("row1"));
        Result r = htable.get(get);
        byte[] b = r.getValue(Bytes.toBytes("cf"), Bytes.toBytes("attr"));  // 最新のバージョンの値を返します.          

10.5.1.3. バージョンを指定した Get の例

次に示す Get では、目的の行の最新の 3 つのバージョンを返します。

        Get get = new Get(Bytes.toBytes("row1"));
        get.setMaxVersions(3);  // 行の最新の 3 つのバージョンを返します.
        Result r = htable.get(get);
        byte[] b = r.getValue(Bytes.toBytes("cf"), Bytes.toBytes("attr"));  // 最新のバージョンの値を返します.
        List<KeyValue> kv = r.getColumn(Bytes.toBytes("cf"), Bytes.toBytes("attr"));  // この列のすべてのバージョンを返します.       
        

10.5.1.4. Put

Put を行うと、特定のタイムスタンプを持つ新しいバージョンのセルが必ず作成されます。デフォルトでは、システムによってサーバーの currentTimeMillis が使われますが、列ごとのレベルでユーザーがバージョン (すなわち long 整数) を指定することもできます。これは、過去または未来の時刻を割り当てたり、時間の表現以外の目的で long 値を使用したりできることを意味します。

既存の値を上書きするには、上書きするセルと正確に同一の行、列、およびバージョンを指定して Put を行います。

10.5.1.4.1. 暗黙的なバージョンの例

次に示す Put では、HBase によって現在の時刻で暗黙的にバージョン管理が行われます。

          Put put = new Put(Bytes.toBytes(row));
          put.add(Bytes.toBytes("cf"), Bytes.toBytes("attr1"), Bytes.toBytes( data));
          htable.put(put);
          

10.5.1.4.2. 明示的なバージョンの例

次に示す Put では、バージョンタイムスタンプを明示的に設定しています。

          Put put = new Put( Bytes.toBytes(row ));
          long explicitTimeInMs = 555;  // 1 例です.
          put.add(Bytes.toBytes("cf"), Bytes.toBytes("attr1"), explicitTimeInMs, Bytes.toBytes(data));
          htable.put(put);
          

10.5.1.5. Delete

HBase で削除操作を実行する場合、削除するバージョンの指定方法には次の 2 つがあります。

  • 特定のタイムスタンプより古いすべてのバージョンを削除する。

  • 特定のタイムスタンプのバージョンを削除する。

削除は、1 つの行全体、1 つの列ファミリ全体、または 1 つの列だけを対象に実行できます。明示的にバージョンを削除できるのは、これらのうち最後のケースだけです。1 つの行、またはファミリ内のすべての列を削除する場合、この削除操作に伴って常に、特定のバージョンより古いすべてのセルが削除されます。

削除操作では、ツームストーンマーカーが作成されます。たとえば、行を 1 つ削除するとします。このとき、バージョンを指定することもできますが、そうしなかった場合にはデフォルトで currentTimeMillis が使われます。これは、このバージョンと等しいか、またはそれより小さいバージョンのすべてのセルを削除することを意味します。HBase はデータをその場で修正することは決して行わないので、削除操作を行っても、削除対象に対応するストレージファイル内のエントリが即座に削除される (または削除されたものとしてマークが付けられる) わけではありません。代わりに、いわゆるツームストーンが書き込まれ、これによって、削除された値をマスクするようになっています[13]。行を削除するときに指定したバージョンが、該当する行のあらゆる値のバージョンより大きい場合には、行全体が削除されることに注意してください。

10.5.2. 現時点での制限事項

バージョンの次元に関しては、依然いくつかバグ (少なくとも「不確実な動作」) があり、これらにバグについては今後の HBase のリリースで対応していく予定です。

10.5.2.1. Put をマスクする Delete

Delete は Put をマスクします。Delete が実行された後に行われた Put も例外ではありません[14]。すでに説明したように、削除操作ではツームストーンが書き込まれ、書き込まれたツームストーンは次にメジャーコンパクションが実行された後に消去されます。たとえば、T 以下であるという条件を満たすあらゆるものを削除し、その後 T 以下のタイムスタンプで新たに Put を実行したとします。この場合、Put は削除操作の後に行われているにもかかわらず、この Put は削除ツームストーンによってマスクされます。Put の実行は失敗しませんが、Get を実行すると、実際には Put が行われなかったことがわかります。この Put は、メジャーコンパクションが実行された後に、機能するようになります。こうした現象は、行に対する新たな Put において、必ず増加するバージョンを使えば、問題にはなりません。しかしこれらの現象は、時間を考慮していない場合、すなわち削除を行った後すぐに Put を実行する場合でも起こることがあり、同じミリ秒内でこれが起こる可能性もあります。

10.5.2.2. メジャーコンパクションによって問い合わせの結果が変わる

... t1、t2、および t3 に 3 つのセルバージョンを作成し、最大バージョン数の設定を 2 にします。すると、すべてのバージョンを取得したときに、t2 と t3 の値だけが返されることになります。しかし、t2 または t3 のバージョンを削除すると、t1 のバージョンが再度現れることになります。もちろん、いったんメジャーコンパクションが実行された後は、このような結果にはなりません...[15]



[10] 現在のところ、最後のものだけを取り出すことができます。

[11] できます。

[12] HBase のバージョンに関する議論については、HBASE-2406を参照してください。「Bending time in HBase」は、HBase のバージョン (すなわち時刻) の次元に関するたいへん優れた解説です。この記事には、このブックよりも詳しいバージョン管理に関する説明があります。本ブックの執筆時点では、記事で言及されている制限「Overwriting values at existing timestamps」は、現在の HBase にはあてはまらなくなっています[訳注: この点についてはリンク先の記事でもすでに訂正されています]。以下のセクションは、基本的にこの Bruno Dumon の記事を要約したものです。

[13] これらのツームストーンは HBase がメジャーコンパクションを行うときに処理され、不要な値とツームストーンそれ自体が実際に消去されます。

[15] Bending time in HBase」の「Garbage Collection」を参照してください。

第11章 アーキテクチャ

11.1. デーモン

11.1.1. Master

11.1.2. リージョンサーバー

11.2. リージョン

この章ではリージョンについて詳しく取り上げます。

注記

リージョンは、列ファミリあたり 1 つの Store から構成されています。

11.2.1. リージョンのサイズ

リージョンのサイズは、取り扱いに注意が必要なものの 1 つで、いくつか考慮すべきことがあります。

  • リージョンは、可用性と分散の基本要素である。

  • HBase は、リージョンが多数のサーバーにちらばっていることでスケールする。したがって、2 つのリージョンで 16GB のデータを扱うとして、これを 20 ノードのマシンで動かせば、明らかに多くの無駄が生じる。

  • リージョン数が多いと動作が遅くなることはすでに知られており、この状況は徐々に改善されてはいるものの、同量のデータに対して 3000 リージョンを用意するよりは、700 リージョンで対処する方がおそらくベターである。

  • リージョン数が少ないと、2 番目のポイントで指摘した並行スケーラビリティを発揮することができない。この点はいくら強調しすぎても足りない。実際、200MB のデータを HBase に読み込んだのに、10 ノードの強力なクラスタがほとんどアイドル状態であることに驚くというのは、よくある話である。

  • リージョンサーバーによって保持されるインデックスなどの点では、1 リージョンと 10 リージョンとで、メモリのフットプリントにそれほど大きな差はない。

おそらく最善の方法はデフォルトを順守することであり、「ホットな」テーブルについては小さめにする (もしくは「ホットな」リージョンを手動で分割して負荷をクラスタ全体に分散させる) か、またはセルのサイズが大きくなる (100KB 以上) 傾向があるなら 1GB のリージョンを使うなどするのが望ましいでしょう。

11.2.2. リージョンの分割

リージョンサーバー上では、分割はほかからの介入なしに行われます。つまり、Master は参加しません。リージョンサーバーはリージョンを分割し、分割されたリージョンをオフラインにした後、ドータリージョンを META に追加し、親のリージョンサーバー上でドータを開いて、分割を行ったことを Master に報告します。分割を手動で管理する方法 (および手動で分割を管理した方がよい理由) については「分割の管理」を参照してください。

11.2.3. リージョンのロードバランサ

一定時間ごと、かつ移行中のリージョンが存在しない場合に限って、クラスタの負荷のバランスを取るために、ロードバランサが起動してリージョンを移動します。ロードバランサが起動する間隔は、設定で指定できます。

11.2.4. Store

Store には 1 つの MemStore と 0 個以上の StoreFile が保持されます。StoreFile は HFile です。

11.2.4.1. HFile

11.2.4.1.1. HFile の形式

hfile のファイル形式は、「BigTable [2006]」という論文に記載された SSTable ファイルと、Hadoop の tfile をベースにしています (ユニットテストスイートと圧縮ツールは直接 tfile から取られました)。Schubert Zhang のブログ記事「HFile: A Block-Indexed File Format to Store Sorted Key-Value Pairs」は、HBase の hfile の非常に優れた入門記事になっています。Matteo Bertozzi も有益な記事「HBase I/O: HFile」を書いています。

11.2.4.1.2. HFile ツール

hfile の内容をテキスト化したものを表示するには、org.apache.hadoop.hbase.io.hfile.HFile ツールを使用します。次のように入力すると、使用法が表示されます。

$ ${HBASE_HOME}/bin/hbase org.apache.hadoop.hbase.io.hfile.HFile  

たとえば、ファイル hdfs://10.81.47.41:9000/hbase/TEST/1418428042/DSMP/4759508618286845475 の内容を表示するには、次のように入力します。

 $ ${HBASE_HOME}/bin/hbase org.apache.hadoop.hbase.io.hfile.HFile -v -f hdfs://10.81.47.41:9000/hbase/TEST/1418428042/DSMP/4759508618286845475  

オプション -v を指定しなければ、hfile のサマリーだけが表示されます。HFile ツールを使ったその他の作業のやり方については、使用法を参照してください。

第12章 先行書き込みログ (WAL)

HBase の先行書き込みログ

各リージョンサーバーは、更新をまず先行書き込みログ (WAL) に追加し、その後メモリに追加します。

12.1. HBase の WAL の目的

Wikipedia の「先行書き込みログ」の記事を参照してください。

12.2. WAL の分割

クラッシュしたリージョンサーバーから編集内容はどのようにして回復されるのか

リージョンサーバーがクラッシュすると、そのリージョンサーバーは ZooKeeper 内の一時的なリースを失います…[要作成]

12.2.1. hbase.hlog.split.skip.errors

true (デフォルト) に設定されていると、分割中に遭遇したエラーはすべて記録され、問題のある WAL は hbase rootdir の下の .corrupt ディレクトリに移動され、処理が続行されます。false に設定されていると、例外が伝達され、分割は失敗として記録されます。[16]

12.2.2. クラッシュしたリージョンサーバーの WAL を分割する際、EOFExceptions はどのように扱われるか

ログの分割中に EOF を受け取ると、hbase.hlog.split.skip.errors == false である場合でも、分割の処理を続行します。分割対象の一連のファイルの中の最後のログを読み取っている最中に EOF に遭遇することは、ほぼ確実です。なぜなら、リージョンサーバーはレコードの書き込み途中でクラッシュした可能性が高いからです。しかし、一連のファイルのうち、最後のファイル以外を読み取っている最中に EOF に遭遇しても、処理は続行します。[17]



[16] HBASE-2958 When hbase.hlog.split.skip.errors is set to false, we fail the split but thats it」を参照してください。このフラグがセットされている場合は、分割を失敗させるだけでなく、それ以上の処理を行う必要があります。

[17] 背景事情については、「HBASE-2643 Figure how to deal with eof splitting logs」を参照してください。

第13章 パフォーマンスチューニング

まず wiki の「Performance Tuning」を読んでください。この記事には、RAM、圧縮、JVM の設定など、パフォーマンスに関係する重要な要素についての全般的な説明があります。記事を読んだら、ここへ戻ってきてください。以下では、さらに詳しい情報へのポインタを示します。

13.1. Java

13.1.1. ガベージコレクタと HBase

13.1.1.1. GC による長時間の一時停止

Todd Lipcon は、「Avoiding Full GCs with MemStore-Local Allocation Buffers」と題したプレゼンテーションの中で、特に HBase の読み込み時によく発生する、すべてが止まったかのような状態になるガベージコレクション、すなわち CMS が失敗するケースと、古い世代のヒープがフラグメンテーション化するケースの 2 つを取り上げています。最初のケースに対処するには、-XX:CMSInitiatingOccupancyFraction を追加してデフォルトより低い値を設定し、CMS をデフォルトよりも早めに開始します。60 パーセントまたは 70 パーセントから開始するようにします (しきい値を低くすると、GC はより多く行われるようになり、CPU の消費量も増えます)。Todd は 2 番目のフラグメンテーションのケースに対処するために、実験的な機能を追加しました。この機能は HBase 0.90.x では明示的に有効にする必要があります (HBase 0.92.x ではデフォルトになりました)。Configurationhbase.hregion.memstore.mslab.enabled に true を設定してください。問題の背景事情と詳細については、上のスライドを参照してください。

13.2. 設定

推奨設定」を参照してください。

13.2.1. リージョンの数

HBase テーブルのリージョンの数は、filesize によって決まります。アーキテクチャの「リージョンのサイズ」も参照してください。

13.2.2. コンパクションの管理

大規模なシステムでは、コンパクションと分割の管理を考慮するべきでしょう。

13.2.3. 圧縮

実働環境のシステムでは、列ファミリの定義で LZO 圧縮などの圧縮を使用するべきです。

13.3. 列ファミリの数

列ファミリの数について」を参照してください。

13.4. データの集中

すべてのデータが 1 つのリージョンに書き込まれている場合には、「時系列データの処理に関する説明」を読み直してください。

13.5. バッチロード

リージョンの事前作成」および「バルクロード」を参照してください。

13.6. HBase クライアント

13.6.1. AutoFlush

多数の Put を実行するときは、HTable インスタンスで setAutoFlush が false に設定されていることを確認してください。false に設定されていないと、Put は一度に 1 つずつリージョンサーバーに送信されます。 htable.add(Put) および htable.add( <List> Put) を介して追加された複数の Put は同一の書き込みバッファに入れられます。autoFlush = false になっている場合、これらのメッセージは、書き込みバッファがいっぱいになるまで送信されません。これらのメッセージを明示的にフラッシュするには、flushCommits を呼び出します。HTable インスタンスに対して close を呼び出すと、flushCommits が呼び出されます。

13.6.2. Scan のキャッシュ

たとえば、HBase が MapReduce ジョブの入力ソースとして使われる場合は、MapReduce ジョブへの入力 Scan インスタンスの setCaching が、デフォルト (すなわち 1) より大きい値に設定されていることを確認してください。デフォルト値を使うと、処理されるすべてのレコードで、map タスクがリージョンサーバーへのコールバックを行うことになります。たとえば、この値を 500 に設定すると、一度に 500 行が処理の対象としてクライアントに送信されます。キャッシュの値を増やすことには、コストとメリットの両面があります。キャッシュの値が増えると、クライアントとリージョンサーバーの両方でより多くのメモリが消費されるので、単に大きければよいというわけではありません。

13.6.3. ResultScanner のクローズ

これは、パフォーマンスの向上ではなく、むしろパフォーマンスに関係する問題を回避することが目的です。ResultScanner をクローズするのを忘れると、リージョンサーバーでさまざまな問題が発生する可能性があります。ResultScanner の処理は、次に示すように必ず try/catch ブロックで囲んでください。

Scan scan = new Scan();
// 属性を設定...
ResultScanner rs = htable.getScanner(scan);
try {
  for (Result r = rs.next(); r != null; r = rs.next()) {
  // 結果を処理...
} finally {
  rs.close();  // 必ず ResultScanner をクローズします!
}
htable.close();

13.6.4. ブロックキャッシュ

Scan インスタンスに対しては、setCacheBlocks メソッドを使うことで、リージョンサーバーのブロックキャッシュを使用するよう設定することができます。MapReduce ジョブへの入力 Scan の場合、この値は false にする必要があります。頻繁にアクセスされる行については、ブロックキャッシュを使用することが推奨されます。

第14章 ブルームフィルタ

ブルームフィルタは、HBase-1200 Add bloomfilters で開発されました。[18][19]

14.1. 設定

ブルームフィルタを有効にするには、HBase Shell で列ファミリに対してオプションを指定するか、または Java のコードで org.apache.hadoop.hbase.HColumnDescriptor に対して設定を行います。

14.1.1. HColumnDescriptor のオプション

HColumnDescriptor.setBloomFilterType(NONE | ROW | ROWCOL) を使用して、列ファミリごとにブルームフィルタを有効にします。デフォルトは NONE で、ブルームフィルタを使用しません。ROW を指定すると、挿入操作ごとに行のハッシュがブルームフィルタに追加されます。ROWCOL を指定すると、キーの挿入操作ごとに、行 + 列ファミリ + 列ファミリ修飾子のハッシュがブルームフィルタに追加されます。

14.1.2. io.hfile.bloom.enabled グローバル kill スイッチ

Configurationio.hfile.bloom.enabled は、適切な動作が行われなかったときに kill スイッチとして使われます。デフォルトは true です。

14.1.3. io.hfile.bloom.error.rate

io.hfile.bloom.error.rate は、平均偽陽性率です。デフォルトは 1% です。平均偽陽性率を ½ 減らす (つまり 0.5% にする) と、ブルームフィルタのエントリあたり 1 ビット増えます。

14.1.4. io.hfile.bloom.max.fold

io.hfile.bloom.max.fold は、保証最低縮小率 (guaranteed minimum fold rate) です。ほとんどのユーザーはこの設定に手を加える必要はないでしょう。デフォルトは 7 で、オリジナルサイズの少なくとも 1/128 まで縮小できます。このオプションの意味の詳細については、ドキュメント『BloomFilters in HBase』の「Development Process」を参照してください。

14.2. ブルームフィルタの StoreFile でのフットプリント

ブルームフィルタは、StoreFile の汎用 FileInfo データ構造にエントリを 1 つ追加し、ついで StoreFile のメタデータセクションに 2 つのエキストラエントリを追加します。

14.2.1. StoreFileFileInfo データ構造内の BloomFilter

14.2.1.1. BLOOM_FILTER_TYPE

FileInfo には BLOOM_FILTER_TYPE エントリがあり、NONEROWROWCOL のいずれかがセットされます。

14.2.2. StoreFile メタデータ内の BloomFilter エントリ

14.2.2.1. BLOOM_FILTER_META

BLOOM_FILTER_META には、ブルームフィルタのサイズ、使用するハッシュ関数などが保持されます。サイズは小さく、StoreFile.Reader のロード時にキャッシュされます。

14.2.2.2. BLOOM_FILTER_DATA

BLOOM_FILTER_DATA は、ブルームフィルタの実際のデータです。オンデマンドで取得されます。LRU キャッシュが有効になっている場合 (デフォルトでは有効です)、LRU キャッシュに格納されます。



[18] 開発プロセスについての説明 (なぜ動的ブルームフィルタではなく静的ブルームフィルタなのか) や、HBase のブルームフィルタと関連のある固有のプロパティの概要、および将来的な方向性については、HBase-1200 に添付されているドキュメント『BloomFilters in HBase』の「Development Process」を参照してください。

[19] ここで説明するブルームフィルタは、実際には HBase ではバージョン 2 のブルームフィルタです。0.19.x までのバージョンの HBase には、European Commission One-Lab Project 034819 での成果をベースとした動的なブルームフィルタのオプションがありました。HBase のブルームフィルタに関する作業の中核部分は、のちに Hadoop に取り込まれ、org.apache.hadoop.io.BloomMapFile として実装されました。バージョン 1 の HBase ブルームフィルタは、うまく動作したことがありませんでした。バージョン 2 は、同じく one-lab での成果を起点としていますが、スクラッチから書き直されています。

付録A ツール

ここでは、管理や分析、フィクスアップ、デバッグのための HBase のツールについて取り上げます。

A.1. HBase hbck

インストールした HBase に対して使う fsck です。

HBase クラスタを対象に hbck を実行するには、次のコマンドを実行します。

$ ./bin/hbase hbck

コマンドからの出力の最後に、OK または INCONSISTENCY のいずれかが表示されます。クラスタで不整合が報告されたら、-details を指定して、さらに詳しい情報を表示させます。不整合となった場合には、その不整合が (クラスタが起動中、リージョンの分割中などで) 一過性のものである可能性があるので、何度か hbck を実行してください。-fix を指定すると、不整合を修正することができます (これは実験的な機能です)。

A.2. HFile ツール

HFile ツール」を参照してください。

A.3. WAL ツール

A.3.1. HLog ツール

HLog の main メソッドを使うと、手動分割とダンプを行うことができます。main メソッドには WAL または分割の生成物、recovered.edits ディレクトリの内容を渡します。

WAL ファイルの内容をテキスト化してダンプするには、次のように入力します。

 $ ./bin/hbase org.apache.hadoop.hbase.regionserver.wal.HLog --dump hdfs://example.org:9000/hbase/.logs/example.org,60020,1283516293161/10.10.21.10%3A60020.1283973724012 

ファイルに問題があると 0 以外の戻り値が返されるので、STDOUT/dev/null にリダイレクトしてプログラムの戻り値を調べれば、ファイルが完全かどうかをテストすることができます。

同様に、ログファイルディレクトリを強制的に分割するには、次のようにします。

 $ ./bin/hbase org.apache.hadoop.hbase.regionserver.wal.HLog --split hdfs://example.org:9000/hbase/.logs/example.org,60020,1283516293161/

A.4. 圧縮ツール

圧縮ツール」を参照してください。

付録B HBase での圧縮

B.1. CompressionTest ツール

HBase には、圧縮が適切にセットアップされているかどうかをテストするためのツールが含まれています。このツールを実行するには、/bin/hbase org.apache.hadoop.hbase.util.CompressionTest と入力してください。ツールの実行方法についての使用法が表示されます。

B.2. hbase.regionserver.codecs

リージョンサーバーに一連のコーデックをテストさせ、いずれかのコーデックが見つからないか、または不適切にインストールされている場合に、リージョンサーバーが起動しないようにするには、hbase-site.xmlhbase.regionserver.codecs という設定を追加し、その値として、起動時にテストするコーデックを指定します。たとえば、hbase.regionserver.codecs の値が lzo,gz になっていて、LZO が存在しないか、または不適切にインストールされている場合、設定の不適切なリージョンサーバーは起動しません。

管理者はこの機能を利用することで、特定のコーデックがインストールされていることが前提になっているクラスタに新しくサーバーを追加する場合などに、問題の発生を未然に防ぐことができます。

B.3. LZO

LZO 圧縮」を参照してください。

B.4. GZIP

一般に GZIP の方が LZO より圧縮率は高くなりますが、動作は遅くなります。HBase のセットアップによっては、圧縮率が高い方が望ましい場合もあります。Java は、Java の GZIP を使用しますが、ネイティブ Hadoop ライブラリが CLASSPATH 上で利用可能である場合はこの限りではなく、その場合には Java の GZIP の代わりにネイティブなコンプレッサを使用します (ネイティブライブラリが存在しない場合には、ログに Got brand-new compressor というメッセージが数多く出力されます。詳細については、「FAQ」を参照してください)。

付録C FAQ

C.1. 全般
ほかにも HBase の FAQ はありますか?
'2011-01-10 12:40:48,407 INFO org.apache.hadoop.io.compress.CodecPool: Got brand-new compressor' というメッセージがログに大量に出力されるのはなぜですか?
C.2. EC2
EC2 に用意したクラスタへのリモート Java 接続ができないのはなぜですか?
C.3. HBase のビルド
ビルドを実行すると、いつも「Unable to find resource 'VM_global_library.vm'」というメッセージが表示されるのはなぜですか?
C.4. 実行時
HBase の読み込み時に一時停止が起こるのはなぜですか?
リージョンサーバーがよくわからない状況でハングするのはなぜですか?
C.5. ○○するにはどうすればよいですか?
HBase では 2 次インデックスはどうなっているのですか?

C.1. 全般

ほかにも HBase の FAQ はありますか?
'2011-01-10 12:40:48,407 INFO org.apache.hadoop.io.compress.CodecPool: Got brand-new compressor' というメッセージがログに大量に出力されるのはなぜですか?

ほかにも HBase の FAQ はありますか?

wiki にアップされている FAQ の「HBase Wiki FAQ」、「Troubleshooting」のページ、および「Frequently Seen Errors」のページを参照してください。

'2011-01-10 12:40:48,407 INFO org.apache.hadoop.io.compress.CodecPool: Got brand-new compressor' というメッセージがログに大量に出力されるのはなぜですか?

HBase ではネイティブバージョンの圧縮ライブラリを使用していないためです。「HBASE-1900 Put back native support when hadoop 0.21 is released」を参照してください。ネイティブライブラリを hadoop から HBase の lib ディレクトリにコピーするか、またはこれらのライブラリへのシンボリックリンクを作成すると、メッセージは表示されなくなります。

C.2. EC2

EC2 に用意したクラスタへのリモート Java 接続ができないのはなぜですか?

EC2 に用意したクラスタへのリモート Java 接続ができないのはなぜですか?

ユーザー向けメーリングリストに投稿された Andrew の回答「EC2 インスタンスへのリモート Java クライアント接続」を参照してください。

C.3. HBase のビルド

ビルドを実行すると、いつも「Unable to find resource 'VM_global_library.vm'」というメッセージが表示されるのはなぜですか?

ビルドを実行すると、いつも「Unable to find resource 'VM_global_library.vm'」というメッセージが表示されるのはなぜですか?

このメッセージは無視してください。エラーではありません。公式に余計なメッセージであると認められています。

C.4. 実行時

HBase の読み込み時に一時停止が起こるのはなぜですか?
リージョンサーバーがよくわからない状況でハングするのはなぜですか?

HBase の読み込み時に一時停止が起こるのはなぜですか?

圧縮が有効になっている場合は、ユーザー向けメーリングリストのスレッド、「Long client pauses with compression」を参照してください。

リージョンサーバーがよくわからない状況でハングするのはなぜですか?

古い JVM (< 1.6.0_u21) を実行していませんか?スレッドダンプを見ると、スレッドがブロックされているように思われるのに、ロックを保持しているスレッドが 1 つもなく、ロックによってすべてのスレッドがブロックされていませんか?「HBASE 3622 Deadlock in HBaseServer (JVM bug?)」を参照してください。conf/hbase-env.sh で、HBase の HBASE_OPTS-XX:+UseMembar を使いすると、問題が解消される可能性があります。

C.5. ○○するにはどうすればよいですか?

HBase では 2 次インデックスはどうなっているのですか?

HBase では 2 次インデックスはどうなっているのですか?

HBase のようなストアにおける 2 次インデックスの保持に関連したさまざまな問題については、優れた解説があります。「HBase, mail # user - Stargate+hbase」というスレッドの中の David Butler のメッセージを参照してください。

要作成: HBase 用に YCSB をセットアップする方法の説明

YCSB は Ted Dunning によって作り直され、maven 化されるとともに、負荷を検証するための機能が追加されました。Ted Dunning の YCSB を参照してください。

索引

シンボル

セル, セル
バージョン, バージョン
列ファミリ, 列ファミリ
列ファミリ修飾子, 列ファミリ
圧縮, HBase での圧縮

H

Hadoop, hadoop

U

ulimit, ulimit

Z

ZooKeeper, ZooKeeper