認証データベースへのHBase/Hadoopの適用
3.1. テーブルスキーマ
HBaseのテーブルスキーマにはロー(Row)とカラム ファミリー(Column Family)があります。ローは一意性制約を持つので、キーとして使えます。そして1つまたは複数あるカラムファミリーは、それぞれの中でカラムを保持しており、そのカラムはテーブルの作成後も動的に増やすことができます。
HBaseのテーブルにおけるローは行単位の操作がアトミックに行えることを保証しています。よって、HBaseのテーブルを認証テーブルとして使用する場合は、ローの値をユーザーIDとして、カラムファミリーの中のカラムをユーザー属性として使用することで、上述の(A)および(B)の要件を満たすことができます。図3に認証テーブルスキーマの概念を示します*2。
図3:認証テーブルスキーマの概念 |
- [*2] タイムスタンプ(Time Stamp)に関しては、本稿では割愛します。詳細はThe Apache HBase Bookの「7.5. Versions」をご参照ください。
3.2. C言語で書かれたプログラムによるHBaseの利用
認証モジュールは、C言語で書かれたOSおよびCPUアーキテクチャ依存の実行形式であり、Javaで書かれたHBaseへ直接接続をすることができません。そこでHP IceWall SSOでは、認証モジュールとHBaseの間にその通信を媒介するための REST型アプリケーションゲートウェイを配置することで、この問題を解決しました。認証モジュールとアプリケーションゲートウェイ間の通信は、HTTPプロトコルを使用し、メソッドとしては更新時にPOST、参照にGETを使用します。HTTPの body部にはJSON形式でデータを載せています。
図4:アプリケーションゲートウェイを経由した接続の概念図(クリックで拡大) |
3.3. コネクションの並列化によるスループットの向上
認証モジュールとアプリケーションゲートウェイ間のHTTP通信は、GETとPOSTが1ログインあたりそれぞれ1回ずつあります。JSON形式でHTTPに載せる認証データは500バイト程度です。この接続での性能を評価し始めた当初、アプリケーションゲートウェイと認証モジュールは単一のコネクションを通じて通信していました。しかしこの場合のスループットの実測値は20-30ログイン/秒程度となり、実用的なものではありませんでした。
そこで、複数のコネクションを同時に使用し並列性を上げることで、1秒あたりのログイン件数の向上を試みました。同一環境でコネクションを100本使用した場合の実測値は2000 ログイン/秒となり、並列性の向上とスループットの向上が比例する結果となりました。なお、これらの値は筆者らが考える最小のサーバー構成でHBaseを利用した場合のものであり、その構成は図6のスケールアウト後の構成に示すものです。
3.4. リージョンサーバー間でのデータ分散
HBaseは2種類のサーバーで構成されます。1つはマスターで、もう1つはリージョン サーバーです。マスターは主に障害時の復旧制御を始めとしたリージョンサーバーの管理を行い、リージョンサーバーはデータベースに格納される実際のデータを扱います。本章では後者のリージョンサーバーに着目します。
リージョンサーバーでは、HBase テーブルのデータをリージョンと呼ばれる単位に分割したものを管理しています。リージョン内のデータは、ローの値をキーとして常に行ごとにソートされた状態で保存されています。よって、登録されるユーザーIDの先頭文字が近いもの同士は、同一のリージョン内に保持される可能性が高くなります。
先頭文字が近いもの同士が多く使用されると、ユーザーID文字列を起因として特定のリージョンサーバーに負荷が集中することでボトルネックが発生し、スループットの低下をまねくという不本意な事態が起こる可能性があります。スループットの低下をまねかないためには、特に書き込み時はランダムにリージョンサーバーへのアクセスが行われることが理想です。
そこでHP IceWall SSOではユーザーID文字列の接頭辞にハッシュ値を付加する機能を選択できるようにしました。図5に示すように、ユーザーIDの並びによっては特定のリージョンに偏って格納されることがありますが(同図左)、ハッシュ値をユーザーIDの前に付加することによって、ユーザーIDの並びによらず、格納されるリージョンが常に均等に散らばります(同図右)。
図5:ユーザーIDへのハッシュ値付加機能の概念図(クリックで拡大) |
3.5. HBase/Hadoopの可用性
認証データベースが停止すれば、全てのユーザーがログインすることができなくなります。認証データベースにとって可用性はとても重要です。
ここではHP IceWall SSOの認証データベースとしてHBaseが動作するサーバーに障害が起きた際、HP IceWall SSOサービスがどのような挙動を示すか、検証結果のグラフを交えてご紹介します。
本章でご紹介する、HBase/Hadoop の障害発生時の挙動は、図2の構成で構築されたHBaseを認証データベースとして使用した際のものです。ここではまず、HBase/Hadoopを構成する各サーバーの役割と、単一障害点に対する冗長化対策を理解していただく必要があります。HBaseの構成要素であるマスターとリージョンサーバーに関しては、「3.4 リージョンサーバー間でのデータ分散」をご参照ください。
Hadoopは、マスターとなる「ネームノード」とワーカーとして実データを扱う「データノード」から構成されます*3。ネームノードはHadoopが提供する分散ファイルシステムのツリーと、ツリーの構成要素であるディレクトリやファイルのメタデータを保持する役割を持ちます。分散ファイルシステムのメタデータはこのサーバー1台で全て管理されているため、現在のHadoopのバージョンではネームノードは単一障害点となります。
本章ではコールドスタンバイするネームノードが動作するサーバーを用意し、Heartbeatによりネームノードの死活監視を、DRBD(Distributed Replicated Block Device)により保持するデータをリアルタイムにミラーリングすることで、可用性の向上を図っています*4。なお、データノードが故障した場合、そのサーバー内に保持されていたデータは他のデータノード上に複製が保存されているため、データを復旧することができます。
- [*3] その他に、ネームノードが保持するメタデータへの編集ログのマージのためにセカンダリネームノードを、HBaseを構成するサーバーが協調するためにZooKeeperをそれぞれ動作させていますが、本稿では割愛します。セカンダリネームノードの詳細に関しては、こちらのリンクを、HBaseのZooKeeperの利用方法に関しては、こちらのリンクをご覧ください。
- [*4] DRBD, Heartbeatの詳細は、それぞれ以下をご参照ください。
DRBD - http://www.drbd.jp/
Heartbeat - http://www.linux-ha.org/wiki/Heartbeat
以下のグラフ1は、毎秒の認証および認可件数を視覚化したもので、横軸の単位は秒、縦軸は件数を表しています。一定の期間(5分間)、HP IceWall SSOに認証/認可を行い続け、その間に認証データベースとして動作するHBaseのいくつかのプロセス、サーバーに障害を発生させています。
グラフ1:障害発生時の認証と認可の挙動(クリックで拡大) |
検証開始から90秒経過後に、単一のサーバー上で動作するデータノード 、リージョンサーバーを同時にダウンさせています。これ以降ダウンしたリージョンサーバーがメモリー上に保持していたデータを他のリージョンサーバーが復元するまで、復旧対象となっているローへの更新、参照操作に対する応答は全て待ち状態となります。
前述の通り、HP IceWall SSOの認証モジュールでは、HBaseへのコネクションを並列化しているため、リージョンサーバープロセスがダウンしてから全てのコネクションが待ち状態になるまでに若干の時間差があることが分かります。
また、認証後に認証モジュールが行うWebアプリケーションへの接続の認可処理は、認証データベースへの接続を必要とせず、メモリー操作だけで完了します。これにより、全てのコネクションが待ち状態になっている際も、ログイン済みのユーザーは問題なくWebアプリケーションへの接続が認可されていることがグラフから読み取れます。
さらに開始から210秒経過後に、動作するサーバーの電源を断つことでネームノード プロセスを停止させています。今回採用したDRBDとHeartbeatを使った高可用性構成では、ネームノード プロセスが停止すると認証が行えなくなる時間(以下ダウンタイム)が発生します。今回は、毎秒の認証件数に表れない程度の非常に短いダウンタイムでしたが、一般的にはもっと長くなる場合があります。HBaseの導入時にネームノードの冗長化を検討する際には、一例として以下のようなダウンタイムを決める要素を考慮する必要があります。
- Heartbeatのポーリング間隔
- データの復旧に使用する編集ログの量
- 障害時に処理を引き継いだネームノードが障害復旧を終える(セーフモードからの脱出)までの時間