HBase Architecture 101 – Storage_3
Monday, October 12, 2009
http://www.larsgeorge.com/2009/10/hbase-architecture-101-storage.html
HFile
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 org.apache.hadoop.hbase.io.hfile.HFile
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 org.apache.hadoop.hbase.io.hfile.HFile -v -p -m -f \
02. hdfs://srv1.foo.bar:9000/hbase/docs/999882558/mimetype/2642281535820134018
03.Scanning -> hdfs://srv1.foo.bar:9000/hbase/docs/999882558/mimetype/2642281535820134018
04….
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://srv1.foo.bar:9000/hbase/docs/999882558/mimetype/2642281535820134018, \
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
20.Fileinfo:
21.MAJOR_COMPACTION_KEY = \xFF
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 ブロック値もダンプする。それは、データ・ファイルの状態をチェックする、素晴らしい方式である。
KeyValue’s
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









