Apache HBase はHadoopデータベースであり、Hadoop分散ファイルシステム( HDFS )に基づいています。 )。 HBaseを使用すると、HDFSに保存されているデータにランダムにアクセスして更新できますが、HDFSのファイルは、作成後にのみ追加でき、不変です。では、HBaseはどのようにして低レイテンシの読み取りと書き込みを提供するのでしょうか。このブログ投稿では、HBaseの書き込みパス(HBaseでデータが更新される方法)について説明します。
書き込みパス HBaseが書き込みまたは削除操作を完了する方法です。このパスはクライアントから始まり、リージョンサーバーに移動し、最終的にデータが HFileと呼ばれるHBaseデータファイルに書き込まれるときに終了します。 。書き込みパスの設計には、リージョンサーバーに障害が発生した場合にデータが失われるのを防ぐためにHBaseが使用する機能が含まれています。したがって、書き込みパスを理解することで、HBaseのネイティブデータ損失防止メカニズムについての洞察を得ることができます。
各HBaseテーブルは、次の3つのカテゴリに分類されるサーバーのセットによってホストおよび管理されます。
リージョンサーバーは、HBaseテーブルの処理に貢献します。 HBaseテーブルは大きくなる可能性があるため、リージョンと呼ばれるパーティションに分割されます。各リージョンサーバーは、これらのリージョンの1つ以上を処理します。リージョンサーバーはHBaseテーブルデータを提供する唯一のサーバーであるため、マスターサーバーがクラッシュしてもデータが失われることはありません。
HBaseデータは、ソートされたマップと同様に編成され、ソートされたキースペースが異なるシャードまたはリージョンに分割されます。 HBaseクライアントは、putまたはdeleteコマンドを呼び出してテーブルを更新します。クライアントが変更をリクエストすると、そのリクエストはデフォルトですぐにリージョンサーバーにルーティングされます。ただし、プログラムでは、クライアントは、自動フラッシュをオフにすることで、クライアント側で変更をキャッシュし、これらの変更をリージョンサーバーにバッチでフラッシュできます。自動フラッシュがオフの場合、変更は、flush-commitsが呼び出されるまで、またはプログラムで設定された、またはパラメーター「hbase.client.write.buffer」で構成されたバッファーサイズに応じてバッファーがいっぱいになるまでキャッシュされます。
行キーはソートされているため、どのリージョンサーバーがどのキーを管理しているかを簡単に判断できます。変更要求は特定の行に対するものです。各行キーは、リージョンサーバーによって提供される特定のリージョンに属しています。したがって、putまたはdeleteのキーに基づいて、HBaseクライアントは適切なリージョンサーバーを見つけることができます。最初に、ZooKeeperクォーラムから-ROOT-リージョンをホストしているリージョンサーバーのアドレスを見つけます。クライアントは、ルートリージョンサーバーから、-META-リージョンをホストしているリージョンサーバーの場所を見つけます。メタリージョンサーバーから、要求されたリージョンにサービスを提供する実際のリージョンサーバーを最終的に見つけます。これは3ステップのプロセスであるため、この高価な一連の操作を回避するために、リージョンの場所がキャッシュされます。キャッシュされた場所が無効な場合(たとえば、不明なリージョンの例外が発生した場合)、リージョンを再配置してキャッシュを更新します。
適切なリージョンサーバーがリクエストを受信した後、HFile内のデータは行キーで並べ替える必要があるため、変更をHFileにすぐに書き込むことはできません。これにより、データを読み取るときにランダムな行を効率的に検索できます。 HFileにデータをランダムに挿入することはできません。代わりに、変更を新しいファイルに書き込む必要があります。各更新がファイルに書き込まれると、多くの小さなファイルが作成されます。このようなソリューションは、後でマージまたは読み取るためのスケーラブルでも効率的でもありません。したがって、変更はすぐには新しいHFileに書き込まれません。
代わりに、各変更は memstoreと呼ばれるメモリ内の場所に保存されます 、ランダム書き込みを安価かつ効率的にサポートします。 memstoreのデータは、HFileのデータと同じ方法で並べ替えられます。 memstoreが十分なデータを蓄積すると、ソートされたセット全体がHDFSの新しいHFileに書き込まれます。 1つの大きな書き込みタスクを完了することは効率的であり、HDFSの長所を活用します。
memstoreへのデータの書き込みは効率的ですが、リスクの要素ももたらします。memstoreに保存されている情報は揮発性メモリに保存されるため、システムに障害が発生すると、すべてのmemstore情報が失われます。このリスクを軽減するために、HBaseは更新を先行書き込みログ( WAL )に保存します。 )memstoreに情報を書き込む前。このようにして、リージョンサーバーに障害が発生した場合、そのサーバーのmemstoreに保存されていた情報をWALから復元できます。
注:デフォルトではWALが有効になっていますが、WALファイルをディスクに書き込むプロセスは一部のリソースを消費します。 WALは無効になっている可能性がありますが、これはデータ損失のリスクが懸念されない場合にのみ実行する必要があります。 WALを無効にすることを選択した場合は、独自のディザスタリカバリソリューションを実装することを検討するか、データ損失の可能性に備えてください。
WALファイルのデータは、HFileとは異なる方法で編成されています。 WALファイルには編集のリストが含まれており、1つの編集は1回の書き込みまたは削除を表します。編集には、変更と変更が適用される地域に関する情報が含まれます。編集は時系列で書き込まれるため、永続性を保つために、ディスクに保存されているWALファイルの最後に追加が追加されます。 WALファイルは時系列で並べ替えられるため、ファイル内のランダムな場所に書き込む必要はありません。
WALが大きくなると、最終的に閉じられ、追加の編集を受け入れるために新しいアクティブなWALファイルが作成されます。これは、WALファイルの「ローリング」と呼ばれます。 WALファイルがロールされると、古いファイルに追加の変更は加えられません。
デフォルトでは、WALファイルはそのサイズがHDFSブロックサイズの約95%のときにロールされます。パラメーター「hbase.regionserver.logroll.multiplier」を使用して乗数を構成し、パラメーター「hbase.regionserver.hlog.blocksize」を使用してブロックサイズを構成できます。 WALファイルも、構成された間隔「hbase.regionserver.logroll.period」に基づいて定期的にロールされます。デフォルトでは1時間ですが、WALファイルのサイズが構成された制限よりも小さい場合でも同様です。
WALファイルのサイズを制限すると、リカバリが必要な場合に効率的なファイルの再生が容易になります。これは、リージョンのWALファイルの再生中に特に重要です。これは、ファイルの再生中は、対応するリージョンが使用できないためです。最終的には、各WALファイルからディスクにすべての変更を書き込み、そのコンテンツをHFileに保持することを目的としています。これが行われた後、WALファイルをアーカイブでき、最終的にLogCleanerデーモンスレッドによって削除されます。 WALファイルは保護手段として機能することに注意してください。 WALファイルを再生する必要があるのは、リージョンサーバーのクラッシュ後に失われる更新を回復するためだけです。
リージョンサーバーは多くのリージョンにサービスを提供しますが、リージョンごとにWALファイルはありません。代わりに、1つのアクティブなWALファイルがリージョンサーバーによって提供されるすべてのリージョン間で共有されます。 WALファイルは定期的にロールされるため、1つのリージョンサーバーに多数のWALファイルが含まれる場合があります。一度にリージョンサーバーごとにアクティブなWALは1つだけであることに注意してください。
「/hbase」のデフォルトのHBaseルートを想定すると、リージョンサーバーインスタンスのすべてのWALファイルは、次のように同じルートフォルダーに保存されます。
/hbase/.logs/<host>, <port>,<startcode>
例:
/hbase/.logs/srv.example.com,60020,1254173957298
WALログファイルの名前は次のとおりです:
/hbase/.logs/<host>, <port>,<startcode>/<host>%2C <port>%2C<startcode>.<timestamp>
例:
/hbase/.logs/srv.example.com,60020,1254173957298/srv.example.com%2C60020%2C1254173957298.1254173957495
WALファイルの各編集には、一意のシーケンスIDがあります。このIDは、編集の順序を維持するために増加します。ログファイルがロールされるたびに、次のシーケンスIDと古いファイル名がメモリ内のマップに配置されます。この情報は、各WALファイルの最大シーケンスIDを追跡するために使用されます。これにより、後で一部のmemstoreがディスクにフラッシュされたときにファイルをアーカイブできるかどうかを簡単に把握できます。
編集とそのシーケンスIDは、リージョン内で一意です。編集がWALログに追加されるたびに、編集のシーケンスIDも最後に書き込まれたシーケンスIDとして記録されます。 memstoreがディスクにフラッシュされると、この領域に書き込まれた最後のシーケンスIDがクリアされます。ディスクに書き込まれた最後のシーケンスIDがWALファイルの最大シーケンスIDと同じである場合、この領域のWALファイルのすべての編集がディスクに書き込まれたと結論付けることができます。 WALファイル内のすべてのリージョンのすべての編集がディスクに書き込まれている場合、分割や再生は不要であり、WALファイルをアーカイブできることは明らかです。
WALファイルローリングとmemstoreフラッシュは2つの別個のアクションであり、一緒に実行する必要はありません。ただし、リージョンサーバーに障害が発生した場合の時間のかかるリカバリを回避するために、リージョンサーバーごとに多くのWALファイルを保持することは望ましくありません。したがって、WALファイルがロールされると、HBaseはWALファイルが多すぎるかどうかを確認し、一部のWALファイルをアーカイブできるようにフラッシュする領域を決定します。
この投稿では、HBaseのデータが作成および/または更新される方法であるHBase書き込みパスについて説明します。その重要な部分は次のとおりです。
HFile形式、WALファイル分割などについては、以降の投稿で説明します。