HDFS チュートリアル: Archiテクチャ、読み取り&書き込み Opera生産

⚡ スマートサマリー

HDFSはHadoopの分散ストレージ層であり、非常に大きなファイルを汎用マシンに複製されたブロックに分割し、単一のNameNodeが trac多くのデータノードが読み取りおよび書き込み要求を確実に処理する一方で、ksメタデータも処理します。

  • 🔘 Archi構造: NameNodeは名前空間イメージと編集ログを保持し、DataNodeは実際のブロックレプリカを保存します。
  • ☑️ ブロックサイズ: Hadoop 1.x ではデフォルトで 64 MB のブロックサイズでしたが、Hadoop 2.x および 3.x ではデフォルトで 128 MB になっています。
  • ✅ レプリケーション: デフォルトでは、ブロックごとに3つのレプリカが作成され、複数のラックに分散されるため、ハードウェア障害が発生してもデータが失われることはありません。
  • 🧪 読み取りパス: FSDataInputStreamとDFSInputStreamは、NameNodeからブロックの位置を取得し、DataNodeから直接バイトをストリーミングします。
  • 🛠️ 書き込みパス: DFSOutputStreamはパケットをキューに入れ、DataStreamerはDataNodeパイプラインを構築し、Ack Queueはパケット損失を防ぎます。
  • 🧭 アクセスオプション: org.apache.hadoop.fs Java APIとhdfs dfsシェルはどちらも、オープン、読み取り、書き込み、クローズの操作に対応しています。

HDFS チュートリアル

HDFSとは何ですか?

HDFSは、汎用ハードウェアのクラスタ上で動作する、非常に大きなデータファイルを保存するための分散ファイルシステムです。耐障害性、拡張性に優れ、拡張も非常に簡単です。HadoopにはHDFS(Hadoop分散ファイルシステム)がバンドルされています。

データが単一の物理マシン上のストレージ容量を超えると、データを複数のマシンに分割することが不可欠になります。マシンのネットワーク全体でストレージ固有の操作を管理するファイル システムは、分散ファイル システムと呼ばれます。HDFS はそのようなソフトウェアの 1 つです。

HDFS Archi構造

HDFS クラスターは主に ネームノード ファイルシステムのメタデータを管理し、 データノード 実際のデータを保存するもの。

  • NameNode: NameNodeはシステムのマスターとみなすことができます。NameNodeは、システム内のすべてのファイルとディレクトリのファイルシステムツリーとメタデータを管理します。メタデータ情報は、「名前空間イメージ」と「編集ログ」という2つのファイルに保存されます。NameNodeは、特定のファイルのデータブロックを含むすべてのDataNodeを認識していますが、ブロックの位置を永続的に保存することはありません。この情報は、システム起動時にDataNodeから毎回再構築されます。
  • DataNode: データノードは、クラスタ内の各マシン上に存在するスレーブであり、実際のストレージ機能を提供します。クライアントからの読み取りおよび書き込みリクエストを処理する役割を担います。

単一のNameNodeでは単一障害点となるため、現在のクラスタでは、アクティブなNameNodeとスタンバイのNameNodeが並行して稼働し、JournalNodeのクォーラムを介して編集ログを共有し、両者間で自動的にフェイルオーバーが行われるようになっている。

HDFS の読み書き操作はブロックレベルで行われます。HDFS のデータファイルはブロックサイズのチャンクに分割され、独立した単位として保存されます。Hadoop 1.x のデフォルトのブロックサイズは 64 MB です。Hadoop 2.x 以降では、デフォルトは dfs.blocksize 128MBです。

HDFS はデータ複製という概念に基づいて動作し、データブロックの複数のレプリカが作成され、クラスター全体のノードに分散されることで、ノード障害発生時のデータの高可用性を実現します。デフォルトの複製係数は 3 です (dfs.replication)、そしてDataNodeがハートビートの送信を停止すると、NameNodeは自動的にそのブロックを別の場所に再複製します。

あなたは知っていますか? HDFS 内のファイルは単一ブロックより小さいため、ブロックのストレージ全体を占有することはありません。

タリアセン・ウェストにおける修復作業について OperaHDFS 内

データ読み取り要求は、HDFS、NameNode、およびDataNodeによって処理されます。読み取り側を「クライアント」と呼びましょう。下の図は、Hadoopにおけるファイル読み取り操作を示しています。

HDFSの読み取り操作におけるデータフローは、クライアント、NameNode、およびDataNode間で行われます。

  1. クライアントは、FileSystem オブジェクトの 'open()' メソッドを呼び出すことで読み取り要求を開始します。FileSystem は DistributedFileSystem 型のオブジェクトです。
  2. このオブジェクトはRPCを使用してNameNodeに接続し、ファイルのブロックの位置などのメタデータ情報を取得します。これらのアドレスはファイルの最初の数ブロックのアドレスであることにご注意ください。
  3. このメタデータ要求に応答して、そのブロックのコピーを持つデータノードのアドレスが返されます。
  4. DataNodeのアドレスが受信されると、FSDataInputStream型のオブジェクトがクライアントに返されます。FSDataInputStreamには、DataNodeおよびNameNodeとのやり取りを処理するDFSInputStreamが含まれています。上記の図に示すステップ4では、クライアントが「read()」メソッドを呼び出すと、DFSInputStreamがファイルの最初のブロックを保持する最初のDataNodeとの接続を確立します。
  5. データはストリーム形式で読み込まれ、クライアントは「read()」メソッドを繰り返し呼び出します。このread()操作の処理は、ブロックの終わりに達するまで続きます。
  6. ブロックの終わりに達すると、DFSInputStream は接続を閉じ、次のブロックの次の DataNode の検索に進みます。
  7. クライアントが読み込みを終えると、close() メソッドが呼び出されます。

書きます OperaHDFS 内

このセクションでは、ファイルを通してデータがHDFSに書き込まれる仕組みを理解します。以下の図を参照してください。 tracパスを書き込むもの。

DataQueue、DataStreamer、およびAck Queueを使用したHDFS書き込み操作パイプライン

  1. クライアントは、DistributedFileSystem オブジェクトの 'create()' メソッドを呼び出すことで書き込み操作を開始し、新しいファイルを作成します。これは、上記の図のステップ 1 に相当します。
  2. DistributedFileSystem オブジェクトは、RPC 呼び出しを使用して NameNode に接続し、新しいファイルの作成を開始します。ただし、このファイル作成操作では、ファイルにブロックは関連付けられません。作成中のファイルが既に存在しないこと、およびクライアントが新しいファイルを作成するための適切な権限を持っていることを確認するのは、NameNode の責任です。ファイルが既に存在する場合、またはクライアントが新しいファイルを作成するための十分な権限を持っていない場合は、IOException がクライアントにスローされます。それ以外の場合は、操作は成功し、NameNode によってファイルの新しいレコードが作成されます。
  3. NameNodeに新しいレコードが作成されると、FSDataOutputStream型のオブジェクトがクライアントに返されます。クライアントはこのオブジェクトを使用してHDFSにデータを書き込みます。データ書き込みメソッドが呼び出されます(図のステップ3)。
  4. FSDataOutputStreamには、DataNodeおよびNameNodeとの通信を管理するDFSOutputStreamオブジェクトが含まれています。クライアントがデータの書き込みを続ける間、DFSOutputStreamはこのデータを含むパケットを作成し続けます。これらのパケットは、DataQueueと呼ばれるキューに格納されます。
  5. このデータキューを利用するDataStreamerというコンポーネントがもう1つあります。DataStreamerはNameNodeに新しいブロックの割り当てを要求し、それによってレプリケーションに使用する適切なDataNodeを選択します。
  6. ここで、レプリケーションのプロセスは、DataNode を使用してパイプラインを作成することから始まります。 この例では、レプリケーション レベル 3 を選択したため、パイプラインには 3 つのデータノードがあります。
  7. DataStreamer は、パイプラインの最初の DataNode にパケットを注ぎます。
  8. パイプライン内の各データノードは、受信したパケットを保存し、それをパイプライン内の次のデータノードに転送します。
  9. DFSOutputStreamは、データノードからの確認応答を待っているパケットを格納するために、「Ack Queue」と呼ばれる別のキューを維持します。
  10. キュー内のパケットの確認応答がパイプライン内のすべての DataNode から受信されると、そのパケットは「Ack キュー」から削除されます。DataNode に障害が発生した場合、このキューのパケットを使用して操作が再開されます。
  11. クライアントがデータの書き込みを完了すると、close() メソッドを呼び出します(図のステップ 9)。close() メソッドの呼び出しにより、残りのデータパケットがパイプラインにフラッシュされ、その後、確認応答を待ちます。
  12. 最終的な確認応答を受信すると、NameNodeに連絡してファイル書き込み操作が完了したことを通知します。

HDFSへのアクセス Java API

このセクションでは、 Java Hadoop のファイル システムにアクセスするために使用されるインターフェイス。

Hadoopのファイルシステムとプログラム的にやり取りするために、Hadoopは複数の Java クラス。org.apache.hadoop.fs というパッケージには、Hadoop ファイルシステム内のファイル操作に役立つクラスが含まれています。これらの操作には、開く、読み取る、書き込む、閉じるなどがあります。Hadoop ファイル API は汎用的で、HDFS 以外のファイルシステムとの連携にも拡張できます。

プログラムによる HDFS からのファイルの読み取り

オブジェクト java.net。URL はファイルの内容を読み取るために使用されます。まず、 Java HadoopのHDFSを認識する URL スキーム。これは、セットを呼び出すことによって行われます。URLStreamHandlerFactory メソッド URL オブジェクトを取得し、FsUrlStreamHandlerFactory のインスタンスを渡します。このメソッドは、1 回だけ実行する必要があります。 JVMしたがって、静的ブロックで囲まれています。

コード例は次のとおりです-

public class URLCat {
    static {
        URL.setURLStreamHandlerFactory(new FsUrlStreamHandlerFactory());
    }
    public static void main(String[] args) throws Exception {
        InputStream in = null;
        try {
            in = new URL(args[0]).openStream();
            IOUtils.copyBytes(in, System.out, 4096, false);
        } finally {
            IOUtils.closeStream(in);
        }
    }
}

このコードはファイルを開いてその内容を読み取ります。HDFS上のファイルのパスは、コマンドライン引数としてプログラムに渡されます。

コマンドラインインターフェースを使用してHDFSにアクセスする

これはHDFSを操作する最も簡単な方法の一つです。コマンドラインインターフェースは、ファイルの読み込み、ディレクトリの作成、ファイルの移動、データの削除、ディレクトリの一覧表示といったファイルシステム操作をサポートしています。

走れる 「$HADOOP_HOME/bin/hdfs dfs -help」 各コマンドの詳細なヘルプを取得するには、ここで「dfs」は複数のサブコマンドをサポートする HDFS のシェルコマンドです。現在の Hadoop リリースでは HDFS DFS は好ましい形式であり、古い形式は Hadoopファイルシステム このコマンドは、サポートされているすべてのファイルシステムに対して同じ処理を実行します。

広く使用されているコマンドのいくつかと、それぞれの詳細を以下に示します。

1. ローカル ファイル システムから HDFS にファイルをコピーします。

$HADOOP_HOME/bin/hdfs dfs -copyFromLocal temp.txt /

このコマンドは、以下の出力に示すように、ローカルファイルシステムからHDFSにtemp.txtファイルをコピーします。

hdfs dfs -copyFromLocal コマンドで temp.txt を HDFS にコピーしています

2. -ls コマンドを使用すると、ディレクトリ内のファイルを一覧表示できます。

$HADOOP_HOME/bin/hdfs dfs -ls /

以下のリストでは、' / ' ディレクトリの下にファイル 'temp.txt' (以前にコピーしたもの) があることがわかります。

hdfs dfs -ls コマンドの出力には、HDFS ルートディレクトリ内の temp.txt がリストされています。

3. HDFS からローカル ファイルシステムにファイルをコピーするコマンド

$HADOOP_HOME/bin/hdfs dfs -copyToLocal /temp.txt

このコマンドは -get オプションと類似しており、2 番目の引数として明示的なローカル保存先パスを指定できます。以下の出力は、temp.txt がローカルファイルシステムにコピーされた例を示しています。

hdfs dfs -copyToLocal の出力は、temp.txt がローカルファイルシステムにコピーされたことを示しています。

4. 新しいディレクトリを作成するコマンド

$HADOOP_HOME/bin/hdfs dfs -mkdir /mydirectory

以下のプロンプトに示すように、コマンドは何も表示せずに完了します。

hdfs dfs -mkdir コマンドで HDFS に /mydirectory フォルダを作成します

ディレクトリが作成されているかどうかを確認してください。これでやり方がわかったはずです😉

よくあるご質問

大きなブロックを使用することで、NameNodeのメタデータを小さく保ち、マッパーがシークする前に長い連続したバイト列を読み取ることができます。そのため、ディスクシーク時間は転送時間のごく一部となり、フルファイルスキャンが高速化されます。

NameNodeはハートビートの受信を停止し、ノードをダウン状態としてマークし、レプリケーション係数を下回ったすべてのブロックを正常なDataNodeに再レプリケーションするようスケジュールします。処理中の書き込みは確認応答キューから回復されるため、クライアントはパケットを失うことはありません。

適切に構成されたクラスタでは、このような動作は発生しません。HDFS High Availability では、アクティブな NameNode とスタンバイの NameNode が動作し、JournalNode を介して編集内容を共有します。ZooKeeper のフェールオーバー コントローラは、アクティブ ノードが応答しなくなった場合に、スタンバイ ノードを自動的に昇格させます。

どちらもデータをHDFSにアップロードします。-copyFromLocalオプションはソースをローカルファイルシステムに限定しますが、-putオプションは別のHDFSパスや標準入力など、サポートされているあらゆるソースを受け入れます。それ以外の動作は同じなので、-copyFromLocalは単に意図を説明するものです。

NameNodeでは、ファイル、ディレクトリ、ブロックごとにメモリが占​​有されるため、数百万もの小さなファイルではディスクがいっぱいになるずっと前にヒープメモリが枯渇してしまう。それらをシーケンスファイル、Avro、ORC、Parquet、またはHARアーカイブにまとめることで、メタデータの管理が容易になる。

レプリケーションでは完全なコピーを3つ保持するため、ストレージコストが200%増加します。Hadoop 3で追加されたイレイジャーコーディングは、代わりにパリティセルを保存することで、約50%のオーバーヘッドで同様の耐久性を実現します。ただし、ストレージコストは安くなりますが、リカバリ時のCPUとネットワークのコストは高くなります。

NameNodeの監査ログとDataNodeのメトリクスに基づいて学習された機械学習モデルは、容量枯渇を予測し、ホットブロックを特定し、ディスクがダウンする前に障害を検出できます。アクセスパターンの異常検出により、暴走ジョブも早期に発見できます。

Copilotは、FileSystem.get、FSDataInputStreamループ、IOUtils.copyBytes呼び出しなど、org.apache.hadoop.fsの定型コードを迅速に生成します。Hadoop 2.xと3.xではAPI名や非推奨メソッドが大きく異なるため、生成されたコードは必ず使用しているHadoopのバージョンと照合して検証してください。