Hadoop本輪読会 第2回

縁あってサイバーエージェント内で水曜隔週で行われているHadoop本輪読会なるマニアックなイベントに参加しています。

ちなみに第1回で1章2章をやったのだけれど、その日は仕事の打ち合わせが長引いてしまいほとんど終わりかけの参加であったというわけで割と何も覚えていません。
第2回はそういった第1回での自分と同様で、仕事の都合で来られない人も何人かいたようで。

ともあれ今回は3章の「Hadoop分散ファイルシステム」

Hadoop分散ファイルシステム、略してHDFS(Hadoop Distributed FileSystem)
Hadoopのパワーを生かすための分散ファイルシステムのお話ですね。

以下復習。

HDFSの得手不得手

得手
  • 非常に大きなファイル
  • ストリーミング型のデータアクセス
  • コモディティハードウェア

基本的にたくさんのマシンで構成したクラスタに大量のデータをどんどん蓄積していくイメージ。

ブロックサイズがデフォルト64MBと非常に大きく、実際にはこれより大きいサイズで運用されるらしい。
高スループットのデータアクセスが可能な仕組みで、データをクラスタ内のマシンに分散して保存することによりスケーラビリティと耐障害性に優れている。

不得手
  • 低レイテンシが求められるデータアクセス
  • 大量の小さなファイル
  • 複数のライターからの書き込みや、任意のファイルの修正

これら不得意な使い方は基本的にするなということなんだと思う。

低レイテンシはダメなのに高スループットってどういうこと?って質問が出てきてたけど、今読んだら「データセット全体を読むのに要する時間は、最初のレコードを読み出すレイテンシよりも重要」って書いてある。
トータルの処理時間を縮めるために初動のレスポンスは重視していないということのようだ。

クラスタの構成

マスター/ワーカーパターンというやつだ。よく知らないがそういうパターンだ。

ネームノード(マスター)はデータのある場所を知っていて、実際のデータはデータノード(ワーカー)にある。
クライアントから問い合わせを受けたネームノードは、その対象データを持っているデータノードをご案内する。(通常はレプリケーションされているので複数ご案内する)
クライアントはデータノードから直接データを持ってくると言う具合。

データはファイル単位ではなくブロック単位で各ノードに分散される。
これによってひとつのファイルが複数のノードにまたがって構成される=ファイルサイズの制限がディスク容量に縛られなくなるので、ペタバイトに及ぶファイルも問題なくファイルシステム内に保存できる。
またブロック単位での保存はレプリケーションとの相性もいいということだ。

ちなみにHDFSのブロックサイズ64MBとか128MBだが、各ノードのファイルシステムのブロックサイズはまた別なので、1MBのファイルをHDFS上に保存してもディスク容量は1MBしか食わないとかそんな話もある。

必要なディスク容量の見積もりとかどうするんだろう。
単純に考えると複製数 * ファイルサイズか。こういう質問とっさに出てきたらいいのに。質問力が弱いなあ。

ネームノードは特に冗長化されていない。
データだけローカルディスクとNFSマウントしたディスクに書いて二重化する。
二重化してなくてネームノードのデータが破壊されたらHDFS内のファイル全部死亡。

フェイルオーバーの仕組みは用意されていないようだ。←こういうのも質問しとけよってかんじですね。
それはHadoopが責任持つところとはまた別の話ということなのかな。
まあリアルタイム性の高い処理を行っているわけでもなさそうだし。

セカンダリネームノードと言うものもあるが、これは名前負け。
ネームノードが落ちたときに代わりにマスタに昇格するような名前だけど、実際の仕事は定期的に名前空間のイメージと編集ログをマージさせること。
一応マスタがクラッシュした際にセカンダリネームノードが持っている情報をもとにある程度は復元できるが、最後のマージとクラッシュまでの間の情報は永久に失われる。

HDFSじゃなくてもHadoopは動く

Hadoopファイルシステムの実装はHDFS以外にもいろいろある。
httpやAmazon S3の上で動くものも。
ただし大規模なデータ処理を行う場合はHDFSやKVSのようなデータローカリティの最適化機能を持っている分散ファイルシステムを使うべき。

「データローカリティの最適化機能」ってどういうことなんでしょう。

Hadoopのファイルシステムとやりとりするインタフェース実装いろいろ

もっとも一般的なのはJavaのAPI。
ファイルの読み書き、ディレクトリの作成、ファイル情報の取得、ファイル一覧の取得と絞り込み、データやファイルの削除といった操作が可能。

コマンドラインのインタフェースもある。(中身Java?)
APIだとCとかWebDAVとかFUSEとか。
特にThriftをサービスとして動かしておくとプロキシとして動作してThriftのAPIを使っていろんな言語からHadoopを操作できる。

データ読み書きの詳細

APIが良きに計らってくれるのでクライアントは中の仕組みが全然分からなくても透過的に利用できる。
なので略。

ではなくてHadoopを利用する上では一応知っておいた方がいいでしょう。
でも説明はめんどいので略。さない。一応がんばってみよう。

読むときはクライアント(のAPI)がネームノードにどのデータノードにデータがあるか聞きに行って、それを聞いたらあとはデータノードから勝手に読むかんじ。
ネームノードは場所を教えるだけ。データを中継したりはしないのでここがボトルネックになることはない。
障害に備えて同じブロックを持っている複数のデータノード教える。一応ネットワークの近い順に教える。
クライアントは障害を見つけたら一応ネームノードに教えるみたいだ。

書くときはクライアントがネームノードに書くぞーって言うと、ネームノードで既存のファイルがないかとかパーミッションとかをチェックする。
そしたらネームノードはデータを書くデータノードをクライアントに返して、クライアントはデータ書き終わったらネームノードに書いたぞーって教える。
レプリケーションするので書き込むデータノードは複数。
書こうとしたデータノードに障害があった場合、一定数のノード(デフォルトは1以上)に書き込みができていれば成功と見なす。
書き込めなかったノードにはあとで非同期でレプリケーションが行われる。

flashとかsyncとかの使いどころがイマイチわからなかった。
syncを呼ぶことで一貫性を保証できるようなので、書き込みつつ適当なタイミングで呼ぶべきってことみたいだけど。

以上、間違ってたらすまんてかんじだ。

distcpによる並列コピー

並列動作で効率よくコピー。
実はMapReduce実装。
Hadoopのバージョンがまったく同じでないと使えない。
マイナーバージョンがひとつ違うだけで使えないそうだ。

Hadoopアーカイブ

小さなファイルをtarのごとく固めて効率よく扱う仕組み。
ネームノードのメモリ消費を押さえることができる。

アーカイブ内へのファイル追加や削除をしたい場合はアーカイブ作り直し。
アーカイブ作るときに元のファイルと同量のディスク容量を食う。
うまくmapに渡せない。

といった話だった。たしか。

以上

やっぱ一回は読んでからいかないと、情報のインプットにいっぱいいっぱいで質問とか出せないですね。

追記

資料上がってました。

第2回 Hadoop本 輪読会 発表資料