Agile Cat — in the cloud

HBase の構造を考える _1

Posted in NoSQL by Agile Cat on December 27, 2009

HBase Architecture 101 – Storage_1
Monday, October 12, 2009


About Me

My Photo

Lars George
I am a Software Engineer by heart and work on large scale, distributed, failover-safe systems. Especially "NoSQL" type storage architectures and their related projects like Hadoop with HBase, Hive, Pig. Or Dynomite, Voldemort, Cassandra and so on. I am offering consulting services in this area and for these products. Contact me at or read about my offer!

View my complete profile

One of the more hidden aspects of HBase is how data is actually stored. While the majority of users may never have to bother about it you may have to get up to speed when you want to learn what the various advanced configuration options you have at your disposal mean. "How can I tune HBase to my needs?", and other similar questions are certainly interesting once you get over the (at times steep) learning curve of setting up a basic system. Another reason wanting to know more is if for whatever reason disaster strikes and you have to recover a HBase installation.

多くのケースにおいて、HBase の隠された局面のひとつは、実際にデータをストアする方式となる。その点について、大多数のユーザーは気にする必要が無いかもしれないが、各種の先進的なコンフィグレーションを学習したいと望むときには、取捨選択のスピードを上げる必要があるかもしれない。まず、”どうしたら HBase をニーズに合わせられるか?” という疑問がある。そして、(ときには重要な)基本的なシステムを設定するための学習曲線を超えた途端に、他の類似する問題が生じてくる。さらに多くのことを知りたくなる理由は、その理由が災害対策であったとしても、HBase インストレーションをリカバーが必要だという点にある。

In my own efforts getting to know the respective classes that handle the various files I started to sketch a picture in my head illustrating the storage architecture of HBase. But while the ingenious and blessed committers of HBase easily navigate back and forth through that maze I find it much more difficult to keep a coherent image. So I decided to put that sketch to paper. Here it is.

私として努力したのは、多様なファイルを取り扱う各クラスを知ることであり、HBase のストレージ・アーキテクチャを例証するスケッチから取り掛かった。 なぜなら、HBase の創造的で恵まれたコミッターたちが、その迷路を自在に前後へとナビゲートするにもかかわらず、一貫したイメージを保持することが極めて難しいと認識した。したがって、私はペーパーにスケッチを描くことに決めた。 しれが、以下のものである。

HBase Large

Please note that this is not a UML or call graph but a merged picture of classes and the files they handle and by no means complete though focuses on the topic of this post. I will discuss the details below and also look at the configuration options and how they affect the low-level storage files.

それは、UML や Call Graph ではないが、取り扱うクラスとファイルをマージしたものである。ただし、このポストのトピックに、完全に焦点を合わせたものでもない。以下に詳細を記述し、さらにコンフィグレーション・オプションと、それらが低レベルのストレージ・ファイルに影響を与える様子にも注目していく。

The Big Picture

So what does my sketch of the HBase innards really say? You can see that HBase handles basically two kinds of file types. One is used for the write-ahead log and the other for the actual data storage. The files are primarily handled by the HRegionServer’s. But in certain scenarios even the HMaster will have to perform low-level file operations. You may also notice that the actual files are in fact divided up into smaller blocks when stored within the Hadoop Distributed Filesystem (HDFS). This is also one of the areas where you can configure the system to handle larger or smaller data better. More on that later.

それらのファイルは、主として HRegionServer のものとして取り扱われる。 ただし、特定のシナリオでは、HMaster でさえ低レベルのファイル操作を必要とするだろう。さらに、Hadoop Distributed Filesystem(HDFS)にストアされるとき、それらのファイルが実際より小さなブロックに分割されることに気付くだろう。この方式は、大きなデータや小さなでデータを適切に操作するような、システムのコンフィグレーションを可能にするための 1つの領域である。そのことについては、後に触れる。

The general flow is that a new client contacts the Zookeeper quorum (a separate cluster of Zookeeper nodes) first to find a particular row key. It does so by retrieving the server name (i.e. host name) that hosts the -ROOT- region from Zookeeper. With that information it can query that server to get the server that hosts the .META. table. Both of these two details are cached and only looked up once. Lastly it can query the .META. server and retrieve the server that has the row the client is looking for.

新しいクライアントが、特定の Row キーを探すために、最初に Zookeeper quorum (Zookeeper ノードの別個のクラスタ)とのコンタクトを取るというのが、一般的な流れである。 Zookeeper から、ROOT リージョンをホストするサーバー名(すなわちホスト名)を検索することで、それが実行される。 この情報を用いることで、そのサーバーにクエリーをかけることが可能となり、.META table をホストするサーバーが取得される。 ここでの 2つの詳細情報は、どちらもキャッシュされ、一度調べられるだけである。最終的に、.META サーバーへのクエリーが可能となり、クライアントが探している Row を持つ、サーバーへの検索が実現される。

Once it has been told where the row resides, i.e. in what region, it caches this information as well and contacts the HRegionServer hosting that region directly. So over time the client has a pretty complete picture of where to get rows from without needing to query the .META. server again.

たとえば、region などの Row が存在する場所と、一度会話が成立すると、その情報をキャッシュし、その region をダイレクトにホスティングする HRegionServer とコンタクトを取る。そして、クライアントは再び .META サーバーへのクエリーを必要とすることなく、Row を取得すべき場所の、きわめて詳細な全体像を、長時間にわたり維持することになる。

Note: The HMaster is responsible to assign the regions to each HRegionServer when you start HBase. This also includes the "special" -ROOT- and .META. tables.

Note: HBase を起動するとき、それぞれの HRegionServer に対して region を割り当てる責任を、HMaster は持つ。 それにより、 "special" -ROOT- と .META table も取り込むことになる。

Next the HRegionServer opens the region it creates a corresponding HRegion object. When the HRegion is "opened" it sets up a Store instance for each HColumnFamily for every table as defined by the user beforehand. Each of the Store instances can in turn have one or more StoreFile instances, which are lightweight wrappers around the actual storage file called HFile. A HRegion also has a MemStore and a HLog instance. We will now have a look at how they work together but also where there are exceptions to the rule.

続いて、HRegionServer は対象となる region をオープンし、それが対応する HRegion オブジェクトを生成する。 HRegion が "open" されるとき、あらかじめユーザーが定義したように、すべてのテーブルに対応する個々の HColumnFamily のための、Store インスタンスが設定される。 HFile と呼ばれる実際のストレージ・ファイルのラッパーである、1つ以上の StoreFile インスタンスを、それぞれの Store インスタンスは持つことができる。 さらに、HRegion は MemStore と HLog のインスタンスを持つ。 ここまでで、それらの協調動作することだけではなく、例外ルールもあることが分かるはずだ。



3回くらいに分けて掲載して良く予定です。 ーーー A.C.


HBase の構造を考える _1
HBase の構造を考える _2
HBase の構造を考える _3
NoSQL Ecosystem とは? _1
Hadoop DFS _ Introduction
エンタープライズ RDBMS を Hadoop で補完 _1
The Anatomy of Hadoop I/O Pipeline _1

HBase の構造を考える _2

Posted in NoSQL by Agile Cat on December 25, 2009

HBase Architecture 101 – Storage_2
Monday, October 12, 2009


Stay Put

So how is data written to the actual storage? The client issues a HTable.put(Put) request to the HRegionServer which hands the details to the matching HRegion instance. The first step is now to decide if the data should be first written to the "Write-Ahead-Log" (WAL) represented by the HLog class. The decision is based on the flag set by the client using Put.writeToWAL(boolean) method. The WAL is a standard Hadoop SequenceFile (although it is currently discussed if that should not be changed to a more HBase suitable file format) and it stores HLogKey’s. These keys contain a sequential number as well as the actual data and are used to replay not yet persisted data after a server crash.

そうなると、どのようにして、実際のストレージへの書き込みが行われるのだろうか?ここでの クライアントは、HRegion インスタンスとのマッチングへ向けて、詳細を手渡すための HRegionServer に対して、HTable.put(Put)リクエストを発行する。その時の最初のデータが、HLog クラスが代行する "Write-Ahead-Log" (WAL) により書き込まれるべきものなら、最初にステップを決定することになる。この決定は、Put.writeToWAL(boolean) メソッドを用いる、クライアントが設定するフラグに基づく。 この WAL とは、スタンダード Hadoop SequenceFile (HBase に合ったファイル形式への変更について、議論の最中であるが)であり、HLogKey をストアする。これらのキーは、連続した番号だけではなく、実際のデータも含む。 そして、サーバーがクラッシュした場合には、その時点で永続化されていないデータを再処理する。

Once the data is written (or not) to the WAL it is placed in the MemStore. At the same time it is checked if the MemStore is full and in that case a flush to disk is requested. When the request is served by a separate thread in the HRegionServer it writes the data to an HFile located in the HDFS. It also saves the last written sequence number so the system knows what was persisted so far. Let"s have a look at the files now.

WAL へのデータ書き込みが行われた直後に、あるいは失敗した直後に、それらのデータは MemStore に配置される。それと同時に、MemStore が一杯になっているかどうかのチェックが行われ、一杯の場合には、ディスクへ向けたフラッシュが要求される。そのリクエストが、HRegionServer 内の別スレッドにより処理されるとき、それらのデータが、HDFS 内のHFile へ向けて書き出される。さらに、連続した最後の番号も保存されるため、これまでに永続化されているデータについても、システムは知ることになる。ここで、ファイル自体を見てみよう。


HBase has a configurable root directory in the HDFS but the default is /hbase. You can simply use the DFS tool of the Hadoop command line tool to look at the various files HBase stores.

HBase は、コンフィグレーションが可能な root ディレクトリを HDFS 内に持つが、デフォルトは / hbase となっている。 各種のファイル HBase ストアを参照する際には、Hadoop コマンド・ライン・ツールから、シンプルに DFS ツールを使うことができる。

01.$ hadoop dfs -lsr /hbase/docs
03.drwxr-xr-x   – hadoop supergroup          0 2009-09-28 14:22 /hbase/.logs
04.drwxr-xr-x   – hadoop supergroup          0 2009-10-15 14:33 /hbase/.logs/,60020,1254172960891
05.-rw-r–r–   3 hadoop supergroup      14980 2009-10-14 01:32 /hbase/.logs/,60020,1254172960891/hlog.dat.1255509179458
06.-rw-r–r–   3 hadoop supergroup       1773 2009-10-14 02:33 /hbase/.logs/,60020,1254172960891/hlog.dat.1255512781014
07.-rw-r–r–   3 hadoop supergroup      37902 2009-10-14 03:33 /hbase/.logs/,60020,1254172960891/hlog.dat.1255516382506
09.-rw-r–r–   3 hadoop supergroup  137648437 2009-09-28 14:20 /hbase/docs/1905740638/oldlogfile.log
11.drwxr-xr-x   – hadoop supergroup          0 2009-09-27 18:03 /hbase/docs/999041123
12.-rw-r–r–   3 hadoop supergroup       2323 2009-09-01 23:16 /hbase/docs/999041123/.regioninfo
13.drwxr-xr-x   – hadoop supergroup          0 2009-10-13 01:36 /hbase/docs/999041123/cache
14.-rw-r–r–   3 hadoop supergroup   91540404 2009-10-13 01:36 /hbase/docs/999041123/cache/5151973105100598304
15.drwxr-xr-x   – hadoop supergroup          0 2009-09-27 18:03 /hbase/docs/999041123/contents
16.-rw-r–r–   3 hadoop supergroup  333470401 2009-09-27 18:02 /hbase/docs/999041123/contents/4397485149704042145
17.drwxr-xr-x   – hadoop supergroup          0 2009-09-04 01:16 /hbase/docs/999041123/language
18.-rw-r–r–   3 hadoop supergroup      39499 2009-09-04 01:16 /hbase/docs/999041123/language/8466543386566168248
19.drwxr-xr-x   – hadoop supergroup          0 2009-09-04 01:16 /hbase/docs/999041123/mimetype
20.-rw-r–r–   3 hadoop supergroup     134729 2009-09-04 01:16 /hbase/docs/999041123/mimetype/786163868456226374
21.drwxr-xr-x   – hadoop supergroup          0 2009-10-08 22:45 /hbase/docs/999882558
22.-rw-r–r–   3 hadoop supergroup       2867 2009-10-08 22:45 /hbase/docs/999882558/.regioninfo
23.drwxr-xr-x   – hadoop supergroup          0 2009-10-09 23:01 /hbase/docs/999882558/cache
24.-rw-r–r–   3 hadoop supergroup   45473255 2009-10-09 23:01 /hbase/docs/999882558/cache/974303626218211126
25.drwxr-xr-x   – hadoop supergroup          0 2009-10-12 00:37 /hbase/docs/999882558/contents
26.-rw-r–r–   3 hadoop supergroup  467410053 2009-10-12 00:36 /hbase/docs/999882558/contents/2507607731379043001
27.drwxr-xr-x   – hadoop supergroup          0 2009-10-09 23:02 /hbase/docs/999882558/language
28.-rw-r–r–   3 hadoop supergroup        541 2009-10-09 23:02 /hbase/docs/999882558/language/5662037059920609304
29.drwxr-xr-x   – hadoop supergroup          0 2009-10-09 23:02 /hbase/docs/999882558/mimetype
30.-rw-r–r–   3 hadoop supergroup      84447 2009-10-09 23:02 /hbase/docs/999882558/mimetype/2642281535820134018
31.drwxr-xr-x   – hadoop supergroup          0 2009-10-14 10:58 /hbase/docs/compaction.dir

The first set of files are the log files handled by the HLog instances and which are created in a directory called .logs underneath the HBase root directory. Then there is another subdirectory for each HRegionServer and then a log for each HRegion.

最初のファイル・セットは、HLog インスタンスが操作するログ・ファイルであり、HBase root ディレクトリの .logs と呼ばれるディレクトリ内に作成される。 続いて、個々の HRegionServer のためのサブディレクトリがあり、さらに、HRegion のためのログが表示されている。

Next there is a file called oldlogfile.log which you may not even see on your cluster. They are created by one of the exceptions I mentioned earlier as far as file access is concerned. They are a result of so called "log splits". When the HMaster starts and finds that there is a log file that is not handled by a HRegionServer anymore it splits the log copying the HLogKey’s to the new regions they should be in. It places them directly in the region’s directory in a file named oldlogfile.log. Now when the respective HRegion is instantiated it reads these files and inserts the contained data into its local MemStore and starts a flush to persist the data right away and delete the file.

その後に続くのは、クラスタ上で見ることはないと思われる、oldlogfile.log と呼ばれるファイルである。前述のとおり、ファイル・アクセスが関与する限り、それらのファイルが、例外処理により生成される。それらは、いわゆる "log splits" の結果である。 HMaster が開始され、もはや HRegionServer に操作されないログファイルが見つかったとき、制御が存在すべき新しい region に HLogKey のログ・コピーが分割される。 そして、region ディレクトリ内の、oldlogfile.log という名前のファイル内に、ダイレクトに配置される。このタイミングで、つまり、個々の HRegion がインスタンス化されるとき、それらのファイルが読み込まれ、その内容であるデータがローカルの MemStore に挿入され、正しい位置に永続化するためのフラッシュが実行されてから、このファイルが削除される。

Note: Sometimes you may see left-over oldlogfile.log.old (yes, there is another .old at the end) which are caused by the HMaster trying repeatedly to split the log and found there was already another split log in place. At that point you have to consult with the HRegionServer or HMaster logs to see what is going on and if you can remove those files. I found at times that they were empty and therefore could safely be removed.

Note: 時々、使い残しの oldlogfile.log.old (もう1つの .old が最後に付く)を見かけるだろうが、それらは、HMaster が繰り返してログ分割を行い、また、所定の場所に別のスプリット・ログを見つけた結果である。 その時点において、HRegionServer および HMaster のログと相談する必要がある。それにより、起こっている事象を知り、また、それらのファイルの削除に関して判断する。その時点で、ファイルの内容が空であれば、安全に削除出できることに気づいた。

The next set of files are the actual regions. Each region name is encoded using a Jenkins Hash function and a directory created for it. The reason to hash the region name is because it may contain characters that cannot be used in a path name in DFS. The Jenkins Hash always returns legal characters, as simple as that. So you get the following path structure:

その後に続くファイルのセットは、実際の region となる。 それぞれの region 名が、Jenkins Hash 関数を用いてコード化され、それのためのディレクトリが作られる。 ハッシュを行う理由は、DFS のパス名に使用できない文字が、region 名に含まれる可能性があるためだ。 Jenkins Hash は、適切な文字と、常にシンプルな形でリターンする。次に取得するのは、以下のパス構造となる:


In the root of the region directory there is also a .regioninfo holding meta data about the region. This will be used in the future by an HBase fsck utility (see HBASE-7) to be able to rebuild a broken .META. table. For a first usage of the region info can be seen in HBASE-1867.

対象となる rehion ディレクトリの root には、その region のメタデータを持つ、.regioninfo が存在する。それは、将来において、破壊された .META table の再生を実現する、HBase fsck ユーティリティ(HBASE-7 を参照)により使用される。 この region 情報に関する最初の用法は、HBASE-1867 で参照できる。

In each column-family directory you can see the actual data files, which I explain in the following section in detail.

それぞれの Column ファミリー・ディレクトリ内では、次のセクションで詳細を説明する、実際のデータ・ファイルが参照される。

Something that I have not shown above are split regions with their initial daughter reference files. When a data file within a region grows larger than the configured hbase.hregion.max.filesize then the region is split in two. This is done initially very quickly because the system simply creates two reference files in the new regions now supposed to host each half. The name of the reference file is an ID with the hashed name of the referenced region as a postfix, e.g. 1278437856009925445.3323223323. The reference files only hold little information: the key the original region was split at and wether it is the top or bottom reference. Of note is that these references are then used by the HalfHFileReader class (which I also omitted from the big picture above as it is only used temporarily) to read the original region data files. Only upon a compaction the original files are rewritten into separate files in the new region directory. This also removes the small reference files as well as the original data file in the original region.

これまでに説明していないものとして、region の分割が、最初の子供を参照するファイルを持つことがあるう。 region 内のデータ・ファイルが、コンフィグレーションされた hbase.hregion.max.filesize より大きくなるとき、その region は 2つに分割される。 そのための処理が、きわめて速く最初に処理されるのは、システムが新しい region 内で 2つのリファレンス・ファイルを作成し、それぞれの半分をホストすると推測されるからである。リファレンス・ファイルの名前は、たとえば1278437856009925445.3323223323 のようなプリフィックスとして、参照されるハッシュ名を持つ ID となる。この リファレンス・ファイルは、少量の情報だけを持つ。 つまり、オリジナル region は分割され、トップあるいはボトムを参照するようになる点がポイントである。 その後に、これらのリファレンスが、オリジナルの region データ・ファイルを読むために、HalfHFileReader クラス(テンポラリなものであるため、上記の図には記載していない)により使用される点に注目すべきだ。 圧縮だけが行われ、オリジナル・ファイルは、新しい region ディレクトリ内の分離されたファイルへと書き直される。さらに、小さなリファレンス・ファイルが削除されるだけではなく、オリジナル region のオリジナルのデータ・ファイルも削除される。

And this also concludes the file dump here, the last thing you see is a compaction.dir directory in each table directory. They are used when splitting or compacting regions as noted above. They are usually empty and are used as a scratch area to stage the new data files before swapping them into place.

そして、最終的なファイルのダンプは以下のようになる。末尾にあるのは、それぞれのテーブル・ディレクト内の リcompaction.dir ディレクトリである。 それは、前述のとおり、region の分割もしくは圧縮に際して使用される。通常、それらは空であり、また、ファイルを所定の場所とスワップする前に、新しいデータ・ファイルを寄せ集めるエリアとして使用される。


HBase の構造を考える _1
HBase の構造を考える _2
HBase の構造を考える _3
NoSQL Ecosystem とは? _1
Hadoop DFS _ Introduction
エンタープライズ RDBMS を Hadoop で補完 _1
The Anatomy of Hadoop I/O Pipeline _1

HBase の構造を考える _3

Posted in NoSQL by Agile Cat on December 24, 2009

HBase Architecture 101 – Storage_3
Monday, October 12, 2009



So we are now at a very low level of HBase’s architecture. HFile’s (kudos to Ryan Rawson) are the actual storage files, specifically created to serve one purpose: store HBase’s data fast and efficiently. They are apparently based on Hadoop’s TFile (see HADOOP-3315) and mimic the SSTable format used in Googles BigTable architecture. The previous use of Hadoop’s MapFile’s in HBase proved to be not good enough performance wise. So how do the files look like?

前述のとおり、私たちは HBase のアーキテクチャの、きわめて低レベルを見ている。 HFile(kudos to Ryan Rawson)が、ひとつの目的だけに焦点を絞って作成される、ストレージ・ファイルの実体である。 その目的とは、高速かつ効率的に HBase のデータをストアすることである。一見したところ、Hadoop の TFile (HADOOP-3315 を参照)に基づき、また、Googles BigTable アーキテクチャで用いられる SSTable フォーマットに類似したものとなっている。 HBase における Hadoop MapFile の以前の用法は、充分なパフォーマンスを提供していないことが証明された。 そのファイルは、どのように見えるのだろうか?


The files have a variable length, the only fixed blocks are the FileInfo and Trailer block. As the picture shows it is the Trailer that has the pointers to the other blocks and it is written at the end of persisting the data to the file, finalizing the now immutable data store. The Index blocks record the offsets of the Data and Meta blocks. Both the Data and the Meta blocks are actually optional. But you most likely you would always find data in a data store file.

このファイルは可変長を持ち、唯一の固定的なブロックは、FileInfo と Trailer のブロックとなる。 上記の図に示すように、Trailer は他のブロックへのポインタを持ち、ファイルに対して永続的データの最後に記述され、不変のデータ・ストアを完結する。Index ブロックは、Data と Meta のブロックの、オフセットについて記録する。 Data と Meta のブロックは、現実には、どちらも任意のものとなる。ただし、データ・ストア・ファイルの中で、常にデータを見たいと思うはずだ。

How is the block size configured? It is driven solely by the HColumnDescriptor which in turn is specified at table creation time by the user or defaults to reasonable standard values. Here is an example as shown in the master web based interface:

そして、ブロック・サイズのコンフィグレーションはどうだろう?それは、ユーザー設定あるいはディフォルト値により、合理的で標準的な結果を得るために、テーブルの作成時に HColumnDescriptor により、1つずつ順番に処理される。 以下に示すのは、マスター Web ベースの、インターフェイスの例である:

{NAME => ‘docs’, FAMILIES => [{NAME => 'cache', COMPRESSION => 'NONE', VERSIONS => '3', TTL => '2147483647', BLOCKSIZE => '65536', IN_MEMORY => 'false', BLOCKCACHE => 'false'}, {NAME => 'contents', COMPRESSION => 'NONE', VERSIONS => '3', TTL => '2147483647', BLOCKSIZE => '65536', IN_MEMORY => 'false', BLOCKCACHE => 'false'}, ...

The default is "64KB" (or 65535 bytes). Here is what the HFile JavaDoc explains:

ディフォルトは、"64KB" (or 65535 bytes)である。 以下に、HFile JavaDoc での説明を転記する:

"Minimum block size. We recommend a setting of minimum block size between 8KB to 1MB for general usage. Larger block size is preferred if files are primarily for sequential access. However, it would lead to inefficient random access (because there are more data to decompress). Smaller blocks are good for random access, but require more memory to hold the block index, and may be slower to create (because we must flush the compressor stream at the conclusion of each data block, which leads to an FS I/O flush). Further, due to the internal caching in Compression codec, the smallest possible block size would be around 20KB-30KB."

ブロックのミニマム・サイズについて、 8KB ~ 1MB のブロック・サイズを、一般的には推奨します。 シーケンシャル・アクセスが主体ならば、大きなブロック・サイズが適しています。しかし、そのように設定すると、(データの解凍があるため)ランダム・アクセスが非効率になります。小さなブロックは、ランダム・アクセスに適していますが、Index ブロックを保持するために大量のメモリが必要とされ、また、生成にも時間がかかります(FS I/O フラッシュを生じる、それぞれのデータ・ブロックの終端において、圧縮ストリームをクリアする必要があるため)。 さらに、Compression コーデックにおける内部キャッシングが要因となり、最も小さくできるブロック・サイズは、およそ 20KB~30KB でしょう。

So each block with its prefixed "magic" header contains either plain or compressed data. How that looks like we will have a look at in the next section.

そのため、"magic" を伴なう個々のブロックは、プレーンなデータあるいは、圧縮されたデータを含むことになる。次のセクションで見るものは、どのように映るだろうか?

One thing you may notice is that the default block size for files in DFS is 64MB, which is 1024 times what the HFile default block size is. So the HBase storage files blocks do not match the Hadoop blocks. Therefore you have to think about both parameters separately and find the sweet spot in terms of performance for your particular setup.

DFS におけるディフォルトのファイル・ブロック・サイズが、64MBであることに気づくだろう。それは、HFile デフォルト・ブロック・サイズの 1024 倍である。 したがって、HBase ストレージ・ファイル・ブロックと、Hadoop ブロックは一致しない。そのため、双方のパラメータについて別個に考え、特定のセットアップにおけるパフォーマンスについて、スイート・スポットを見いだす必要がある。

One option in the HBase configuration you may see is hfile.min.blocksize.size. It seems to be only used during migration from earlier versions of HBase (since it had no block file format) and when directly creating HFile during bulk imports for example.

参照される可能性のある、HBase コンフィグレーションにおけるひとつの選択肢が、hfile.min.blocksize.size である。それは、従来の HBase バージョン(ブロック・ファイル形式を持たないため)からの移行において、また、例えばバルク・インポートでダイレクトに HFile を作成するときだけに、使用されると思われる。

So far so good, but how can you see if a HFile is OK or what data it contains? There is an App for that!

そこまでは良いが、Hfile が OK なのかどうか、また、どのようなデータ含まれるのかという点で、何を確認すれば良いのか? 如何に、そのためのアプリケーションを示す!

The HFile.main() method provides the tools to dump a data file:

この HFile.main() メソッドは、データ・ファイルをダンプするためのツールを提供する:

01.$ hbase
02.usage: HFile  [-f <ARG>] [-v] [-r <ARG>] [-a] [-p] [-m] [-k]
03. -a,–checkfamily    Enable family check
04. -f,–file <ARG>     File to scan. Pass full-path; e.g.
05.                            hdfs://a:9000/hbase/.META./12/34
06. -k,–checkrow       Enable row order check; looks for out-of-order keys
07. -m,–printmeta      Print meta data of file
08. -p,–printkv        Print key/value pairs
09. -r,–region <ARG>   Region to scan. Pass region name; e.g. ‘.META.,,1′
10. -v,–verbose        Verbose output; emits file and meta data delimiters

Here is an example of what the output will look like (shortened here):


01.$ hbase -v -p -m -f \
02. hdfs://
03.Scanning -> hdfs://
05.K: \x00\x04docA\x08mimetype\x00\x00\x01\x23y\x60\xE7\xB5\x04 V: text\x2Fxml
06.K: \x00\x04docB\x08mimetype\x00\x00\x01\x23x\x8C\x1C\x5E\x04 V: text\x2Fxml
07.K: \x00\x04docC\x08mimetype\x00\x00\x01\x23xz\xC08\x04 V: text\x2Fxml
08.K: \x00\x04docD\x08mimetype\x00\x00\x01\x23y\x1EK\x15\x04 V: text\x2Fxml
09.K: \x00\x04docE\x08mimetype\x00\x00\x01\x23x\xF3\x23n\x04 V: text\x2Fxml
10.Scanned kv count –> 1554
11.Block index size as per heapsize: 296
12.reader=hdfs://, \
13.  compression=none, inMemory=false, \
14.  firstKey=US6683275_20040127/mimetype:/1251853756871/Put, \
15.  lastKey=US6684814_20040203/mimetype:/1251864683374/Put, \
16.  avgKeyLen=37, avgValueLen=8, \
17.  entries=1554, length=84447
18.fileinfoOffset=84055, dataIndexOffset=84277, dataIndexCount=2, metaIndexOffset=0, \
19.  metaIndexCount=0, totalBytes=84055, entryCount=1554, version=1
22.MAX_SEQ_ID_KEY = 32041891
23.hfile.AVG_KEY_LEN = \x00\x00\x00\x25
24.hfile.AVG_VALUE_LEN = \x00\x00\x00\x08
25.hfile.COMPARATOR = org.apache.hadoop.hbase.KeyValue\x24KeyComparator
26.hfile.LASTKEY = \x00\x12US6684814_20040203\x08mimetype\x00\x00\x01\x23x\xF3\x23n\x04

The first part is the actual data stored as KeyValue pairs, explained in detail in the next section. The second part dumps the internal HFile.Reader properties as well as the Trailer block details and finally the FileInfo block values. This is a great way to check if a data file is still healthy.

最初のパートは、KeyValue のペアとしてストアされる実際のデータであり、次のセクションで詳細に説明する。 2番目のパートは、内部にある HFile.Reader のプロパティだけではなく、 Trailer ブロックの詳細をダンプし、最終的に FileInfo ブロック値もダンプする。それは、データ・ファイルの状態をチェックする、素晴らしい方式である。


In essence each KeyValue in the HFile is simply a low-level byte array that allows for "zero-copy" access to the data, even with lazy or custom parsing if necessary. How are the instances arranged?

本質的に、HFile の個々の KeyValue は、低レベルのバイト・アレイであり、レイジーもしくはカスタムなパージングが必要であっても、対象となるデータへの "zero-copy" アクセスを可能にする。そして、どのようにインスタンスは配置されるのだろうか?


The structure starts with two fixed length numbers indicating the size of the key and the value part. With that info you can offset into the array to for example get direct access to the value, ignoring the key – if you know what you are doing. Otherwise you can get the required information from the key part. Once parsed into a KeyValue object you have getters to access the details.

このストラクチャは、キーと値のパートについて、そのサイズを示す 2つの固定長数により始まる。それらの情報を用いて、たとえば値へのダイレクト・アクセスを得るために、キーを無視して、アレイをオフセットできるが、何か起こるのか、知っている必要がある。さもなければ、キーのパートから、必要な情報を取得することになる。 一度、KeyValue オブジェクトへと解析されると、細部にアクセスするための getter を持つことになる。

Note: One thing to watch out for is the difference between KeyValue.getKey() and KeyValue.getRow(). I think for me the confusion arose from referring to "row keys" as the primary key to get a row out of HBase. That would be the latter of the two methods, i.e. KeyValue.getRow(). The former simply returns the complete byte array part representing the raw "key" as colored and labeled in the diagram.

Note: 警戒するべきことは、KeyValue.getKey () と KeyValue.getRow () の間の相違である。 私の場合は、HBase から Row を取りを出すために、主キーとして "row keys" を参照したことに、混乱の原因があった。それは、2つのメソッドの後者、すなわち KeyValue.getRow () のはずだ。前者は、このダイアグラムのカラー・ラベルとしての、ナマの ”key” を表示する、完全なバイト・アレイ・パートをリターンする。

This concludes my analysis of the HBase storage architecture. I hope it provides a starting point for your own efforts to dig into the grimy details. Have fun!

以上が、HBase ストレージ・アーキテクチャに関する私の分析である。これが、厄介な詳細を探求する、あなた自身の作業の出発点になることを希望する。 楽しんで行こう!

Update: Slightly updated with more links to JIRA issues. Also added Zookeeper to be more precise about the current mechanisms to look up a region.

Update 2: Added details about region references.

Update 3: Added more details about region lookup as requested.

Posted by Lars George



間違いや、勘違いなど、ここはオカシイというのがありましたら、ご指摘くださ~い。 ーーー A.C.

HBase の構造を考える _1
HBase の構造を考える _2
HBase の構造を考える _3
NoSQL Ecosystem とは? _1
Hadoop DFS _ Introduction
エンタープライズ RDBMS を Hadoop で補完 _1
The Anatomy of Hadoop I/O Pipeline _1

%d bloggers like this: