Hadoop HBase part2

ということで,HBaseについて.

最近,Hadoop内でも特に活発に開発されているHBaseについてです.これは,Google Bigtableの再実装ですね.HBase Architectureを読んでみたまとめを書いておきます.第2弾です.Client APIについては,JavaDoc読めとのこと.後回し.

HRegion (Tablet) Server
ユーザにとっては,普通のテーブルに見えるけど,内部的には,HRegionsに分かれています.HRegionは,テーブル名とstart/end key pairによって一意に決定されます.で,複数のHRegionServerを扱うことによって,ユーザは,データを利用できます.このとき,HRegionServerは,1台に1プロセス存在し,あるHRegionは一度に一つのHRegionServerしかアクセスできません.

ユーザがデータを更新するときには,(更新に)関連するHRegionServerへアクセスし,HRegionをコミットします.で,コミットの時点で,そのデータは,HRegionのHMemcacheとHRegionServerのHLogへ追加されます.HMemcacheは,メモリバッファであり,一番直近のデータをストア・管理します.HLogは,ディスク上にあって,全ての更新を追跡します.commit()関数は,更新がHLogに書かれるまで返り値を戻しません.

データを取り出すときには,まず,HRegionは,HMemcacheをチェックします.もしも,データが無い場合,ディスク上のHStoresをチェックします.一つのHRegion内に,それぞれのカラムファミリーに対してひとつのHStoreが存在します.HStore自信は,複数のHStoreFilesから構成されます.高速アクセスを目指すために,HStoreFileは,B-Treeライク構造を持っています.
定期的に,HRegion.flushcache()を呼び出して,HMemcacheにあるデータをHStoreのファイル群に書き込みます.このとき,新しいHStoreFileがそれぞれのHstoreへ追加されます(?なんで?).HMemcacheが空になったら,HLogにフラッシュされたことを示すトークンを書き込みます(チェックポイントだね).

起動時には,それぞれのHRegionは,HLogに何らかの書き込みがあったかどうかをチェックします(直近のflushcache()を調べます).もしなければ,全ての関連するHRegionのデータは,HStoreに書き込まれていることになります.もし,チェックポイント以降のデータがあれば,HLogから更新されたデータを再構築し,HMemcacheへそのデータを書いて,flushcache()を呼び出します.最後に,HLogを消してデータの利用が可能になります.#うん?HLogのデリートしちゃうのか?
そのようにして,flushcache()を少なく呼べば,仕事も少なくて済みます.しかし,HMemcacheは,より多くのメモリを消費し,再起動時の再構築作業が長くなります.もし,flushcache()を頻繁に呼べば,HMemcacheのメモリは少なくなり,HLogの再構築は早くなりますが,flushcache()はオーバヘッドを引き起こすことになります.

HLogは,定期的にローテションするので,複数の時系列的にソートされた複数のファイル.HLogをローテションするときには,HLogは,一番古いlog fileを削除します(当然フラッシュ済み).HLogのローテーションにかかる時間はとても短くて,継続的に行うには良い.flushcache()が呼び出されると,HStoreFileをHStoreへ追加します.なので,HStoreからフェッチするときには,これらのStoreFilesに一度にアクセスすることが可能になります.このこと自体は,時間がかかるので,定期的にこれらのHStoreFilesを一つの大きなファイルへコンパクト化します.これは,HStore.compact()によって実現されています.コンパクションの実行は重たいので,バックグラウンドで実行されます.HStoreFilesの数が設定された閾値を超えた場合に実行されます.

Bigtableのペーパーでは,major/minorコンパクションがあるけど,ちょっと複雑.以下のことに気をつけています.
1.flushcache()は,メモリバッファからあふれた全ての更新をディスクへ書き込みます.flushcache時に,log再構築時間はゼロにします.
各flushcache()は,新しいHStoreFileをそれぞれのHStoreへ追加します.
2.compact()は,全てのHStoreFilesを一つに統合します.
Bigtableと違って,HBaseでは,更新がコミットされたけれどもログにかかれていないという状態を許しません.ただまぁ,もし本当に必要であれば,この機能を追加するのは簡単です.HRegion.closeAndMerge()を用いて,二つのHRegionsを新しい一つのHRegionにマージすることが可能です.現時点では,これをやるときには,両方のregionがオフラインである必要があります.

regionが設定値よりも大きくなった場合,HRegion.closeAndSplit()が呼び出されます.親regionを分割することで新しい二つのregionが作られます.新しいregionsはマスタ(サーバ)へどのサーバがどの娘regionをホストするのかを通知します.分割は大抵高速ですが,その理由は,娘のrigionは,親regionのもつファイルへの参照を持つからです.一人目の娘は,上半分,二人目は,下半分を持ちます.この参照が配置される間,親regionはオフラインになり,コンパクションが終了し,親regionが取り除かれることになるまで,特に何もしません.

まとめてみますと,
1.クライアントはテーブルのデータにアクセスします
2.テーブルは,HRegionsへ分解されます.
3.HRegionsは,HRegionServerによって管理されます.クライアントは,サーバが持つレコード範囲にあるレコードにアクセスするため,
HRegionServerにアクセスします.
4.HRegtionは,データを以下に格納します.
4.1. HMemcache:最近書かれたデータのメモリバッファ
4.2. HLog:最近の書き込みに対する,書き込みログ
4.3.HStrore:ファイルの集合.カラムグループに一つ存在する.

Hadoop HBase part3

ということで,HBaseについて.

最近,Hadoop内でも特に活発に開発されているHBaseについてです.これは,Google Bigtableの再実装ですね.HBase Architectureを読んでみたまとめを書いておきます.第3弾です.このエントリで翻訳は終了です.

HBase Master Server
それぞれのHRegionServerは,一つのHMasterにコンタクトし続けます.HMasterは,それぞれのHRegionServerに対して,どのHRegionをロードし,制御可能にしなければいけないかを通知する責任を持ちます.HMasterは,集計表を管理します.これは,どのHRegionServersが有効かを示します.もし,HRegionServerとHMasterの接続がタイムアウトになった場合,
1.HRegionServerは自分自身をkillし,空の状態で再起動します.
2.HMasterは,HRegionServerが死んだものとして,管理していたHRegionsを他のHRegionServersへ再配置します.
これは,Bigtableとは違うところですが,TabletServerは,Masterへの接続が死んだ後でも,Tabletsを管理します.この辺の制御をつなげた理由としては,Bigtableのように外部にロックマネージャーを持っていなかったためです.Bigtableでは,ひとつのMasterがあり,それは,tabletsを配置し,lock mager(chubby)も配置します.chubbyは,複数のTabletServersがtabletsにアトミックなアクセスを保証します.HBaseは全てのHRegtionServersへのアクセスに対して,一つの中心的なモジュールで管理します.それが,HMasterです.(これは,Bigtableと同様に危険ではない.それぞれのシステムは,ネットワーク構造上信頼がおける.HMasterもChubbyもデータシステムが
生きている限り行き続けなければなりません.Chubbyもつ長所はあるけど,ひとまずおいておきます.

HRegionServerが新しいHasterの元でチェックするときには,HMasterはそれぞれのHRegionServerへ,0個以上のHRegionsを割り当てることができるか聞きます.もし,HRegtionServerが志望しているときには,HMasterは,これらのHRegionsを配置していないものとして
マークします.その後,別のHRegionServersへの配置を試みます.それぞれのHRegionがテーブル名とそのキー範囲によって特定されたのを思い出して欲しい.キー範囲は,contiguousであるので,rangesは,いつもスタートを持ち,NULLエンドをもつ.よって,start-keyを示すだけで十分である.
#これは,つまり,範囲と入っているけど,1-100を二つに分割した場合に,1-50, 51-100となり,50と51がcontiguousだから,実質的に
#50の意味がないということだと思う.
で,実は,これは十分ではないです.それは,merge()とsplit()があるから,(処理が終わるまでは)同じ名前で全く違う二つのHRegionsが存在します.もし,システムがその時点で落ちたとするなら,両方のHRegionsが同時に存在してしまう.どちらのHRegionが正しいかの仲裁は,HBaseのめた情報にあります.同じHRegionの別バージョンを区別するために,HRegion nameに対してユニークなregionIdをつける必要があります.結局,idは,HRegion: tablename + startkey + regionIdを意味しています.例えば,以下のようにあらわされます
hbaserepository,w-nk5YNZ8TBb2uWFIRJo7V==,6890601455914043877

META Table
このidentifierを別のHRegionにあるrow-labelとして使うことも可能です.HRegionmeta-infoはHRegion内に格納されます.このテーブルをMETAテーブルと呼びます.このテーブルは,HRegion identifiersから物理的なHRegionServer上の配置場所への変換テーブルとなっています.METAテーブルそのものは,大きくなりますので,分割されます.全てのMETAテーブルを配置するためにROOTテーブルに全てのMETA HRegionsのリストを持たせます.ROOTテーブルは必ず一つのHRegionに含まれます.起動時には,HMasterは直ちにROOTテーブルをスキャンしようとします.なぜかというと,唯一つのHRegionが存在し,そいつの名前はHard-Codedだからです.なので,ROOTテーブルがどこかのHRegionServerに配置されるまで,待たないといけません.一度,ROOTテーブルが利用可能になると,HMasterはそのテーブルをスキャンし,全てのMETA HRegionsを得ます.そうしたら,METAテーブルをスキャンします.このときもまた,全てのMETA HRegionsが別のHRegionServersに配置されるまで待たなければなりません.最後に,HMasterがMETAテーブルをスキャンしたとき,HMasterは,HRegionsの全ての集合を知ることになります.そうなったら,それらのHRegionsをHRegionServersへ配置します.HMasterは,現在動作中のHRegionServersをメモリ上で管理します.HMasterが死ぬということは,システム全体が死亡することなので,ディスク上にこれらの情報を格納する意味はありません.
#すげー割り切り.さすがだ.

Bigtableでは,Tablet ->TabletServerのマッピングはChubbyに入っています.Bigtableと違って,HRegion ->HRegionServerのマッピングは物理的にMETAテーブルに格納されてます(chubbyが無いので仕方ない.).

まとめると,METAテーブル及びROOTテーブルのそれぞれのレコードは三つのメンバをinfo: calumn familyに持っています.
1.info:regioninfo:はシリアル化されたHRegionInfo オブジェクトを持ちます.
2.info:server:は,HServerAddress.toString()によって得られたシリアル化された文字列を持ちます.この文字列は,HServerAddressの一つに供給されます(??).
3.info:startcode:は,シリアル化されたlong
intergerで,HRegionServerのスタート時に作成されます.HRegionServerはスタートコードをマスタへ送り,
META/ROOT regionsに書かれている情報が古いかどうかを確認する.このようにして,ROOT HRegionの場所が分かった後では,クライアントは,HMasterへコンタクトしなくてすむ.HMasterへの負荷は相対的に軽い.HMasterは,HRegionServersのタイムアウト,起動時のROOT/METAのスキャン,ROOT HRegionの場所を管理することが仕事です.

Hbaseクライアントは,(喜んで)複雑です.特定のユーザテーブルをスキャンすることを要求されたときなどは,ROOTやMETA
HRegionsをナビゲートする必要があります.もし,HRegionServerが利用できない,または,持っているべきHRegionを持っていない場合には,クライアントはちょっと待ってからリトライします.起動時やHRegionServerがこけたとき,HRegionからHRegionServerへの正しいマップはりよう不能になります.