Hadoop の分散ファイル ストレージ システムの HDFS コンポーネントの使用

1. HDFSの構成

1、名前ノード

  • HDFS クラスター全体のメタデータ (クラスター全体に保存されているディレクトリとファイルのインデックス) を保存します。
  • HDFS クラスター全体を管理する
  • クライアントリクエストを受信する
  • ノードのフェイルオーバーを担当します

2、データノード

  • データはブロックの形式で保存されます。
  • デフォルトのブロック サイズは 128M です。
  • ブロックサイズサイズの計算式:
    • シーク時間: ファイルのダウンロード時にファイルを見つけるのにかかる時間。最良の状態はシーク時間が送信時間の 1% のときです。HDFS の平均シーク時間は 10 ミリ秒です。
    • データ伝送速度: 100M/s
  • ノード全体に保存されているブロック情報を定期的に要約し、それを NN に報告する役割を果たします。
  • クライアントと接続してファイルの読み取りおよび書き込み操作を実行します。

3、セカンダリ名ノード

  • NameNode が編集ログと fsimage イメージ ファイルのマージ操作を完了するのを支援します。

4. クライアント: コマンドライン/Java API

  • HDFS クラスターと通信してファイルを追加、削除、変更、確認する責任を負います。
  • ブロックのセグメント化を担当します

2. HDFS の基本的な使用方法

HDFS は、データ (ファイル データ) を保存できる分散ファイル ストレージ システムです。HDFS はファイル システムであるため、ファイルのアップロード、ダウンロード、削除、フォルダーの作成などを行うことができます。

HDFS では、次の 2 つの操作方法が提供されます。 ① コマンドライン操作 ② Java API による操作

1. コマンドライン操作

命令行操作
hdfs dfs -xxxx xxxxx 或者 hadoop fs -xxxx xxxxx
查看 —— hdfs dfs -ls/
新建 —— hdfs dfs -mkdir /demo
上传 —— hdfs dfs -put jdk-8u371-linux-x64.tar.gz /demo
上传并删除Linux本地内容 —— hdfs dfs -moveFromLocal hadoop-3.1.4.tar.gz /demo
下载 —— hdfs dfs -getToLocal /demo/hadoop-3.1.4.tar.gz /opt/software
下载 —— hdfs dfs -copyToLocal /demo/hadoop-3.1.4.tar.gz /opt/software
删除 —— hdfs dfs -rm -r /demo

2. Java APIの操作

Hadoop プログラミングの依存関係 (hadoop-client、hadoop-hdfs) を pom.xml に導入します。

<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
  xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
  <modelVersion>4.0.0</modelVersion>

  <groupId>com.kang</groupId>
  <artifactId>hdfs-study</artifactId>
  <version>1.0-SNAPSHOT</version>
  <packaging>jar</packaging>

  <name>hdfs-study</name>
  <url>http://maven.apache.org</url>

  <properties>
    <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
    <maven.compiler.source>8</maven.compiler.source>
    <maven.compiler.target>8</maven.compiler.target>
    <hadoop.version>3.1.4</hadoop.version>
  </properties>

  <dependencies>
    <dependency>
      <groupId>junit</groupId>
      <artifactId>junit</artifactId>
      <version>4.12</version>
      <scope>compile</scope>
    </dependency>
    <!-- https://mvnrepository.com/artifact/org.apache.hadoop/hadoop-client -->
    <dependency>
      <groupId>org.apache.hadoop</groupId>
      <artifactId>hadoop-client</artifactId>
      <version>${hadoop.version}</version>
    </dependency>
    
    <!-- https://mvnrepository.com/artifact/org.apache.hadoop/hadoop-hdfs -->
    <dependency>
      <groupId>org.apache.hadoop</groupId>
      <artifactId>hadoop-hdfs</artifactId>
      <version>${hadoop.version}</version>
    </dependency>
  </dependencies>
</project>
  • HDFの基本操作
/**
 * HDFS的编程流程
 *   1、创建Hadoop的配置文件对象,配置文件对象指定HDFS的相关连接配置
 *        配置文件对象等同于hadoop的etc/hadoop目录下的哪些xxx.xml配置
 *   2、根据配置获取和HDFS的连接
 *   3、连接去操作HDFS集群
 */

import org.apache.hadoop.conf.Configuration;
import org.apache.hadoop.fs.FileSystem;
import org.apache.hadoop.fs.LocatedFileStatus;
import org.apache.hadoop.fs.Path;
import org.apache.hadoop.fs.RemoteIterator;

import java.io.IOException;
import java.net.URI;
import java.net.URISyntaxException;

public class Demo {
    
    
    public static void main(String[] args) throws URISyntaxException, IOException, InterruptedException {
    
    
        //1、创建Hadoop的配置文件Configuration对象
        Configuration conf = new Configuration();
        //2、根据配置文件获取HDFS的连接 FileSystem
        FileSystem system = FileSystem.get(new URI("hdfs://192.168.31.104:9000"), conf, "root");
        //3、根据System去操作HDFS集群了
        RemoteIterator<LocatedFileStatus> listedFiles = system.listFiles(new Path("/"), false);
        while(listedFiles.hasNext()){
    
    
            LocatedFileStatus fileStatus = listedFiles.next();
            System.out.println("文件的路径" + fileStatus.getPath());
            System.out.println("文件的所属用户" + fileStatus.getOwner());
            System.out.println("文件的权限" + fileStatus.getPermission());
            System.out.println("文件的blocksize" + fileStatus.getBlockSize());
        }
    }
}

画像-20230719175628635

画像-20230719175607666

import org.apache.hadoop.conf.Configuration;
import org.apache.hadoop.fs.FileSystem;
import org.apache.hadoop.fs.Path;
import org.junit.Before;
import org.junit.Test;

import java.io.IOException;
import java.net.URI;
import java.net.URISyntaxException;

/**
 * 单元测试
 */
public class HDFSTest {
    
    
    public FileSystem fileSystem;

    @Before
    public void init() throws URISyntaxException, IOException, InterruptedException {
    
    
        //1、创建Hadoop的配置文件Configuration对象
        Configuration conf = new Configuration();
        conf.set("dfs.replication","1");
        //2、根据配置文件获取HDFS的连接 FileSystem
        fileSystem = FileSystem.get(new URI("hdfs://192.168.31.104:9000"), conf, "root");
    }
    /**
     * 1、通过JavaAPI实现文件的上传
     */
    @Test
    public void test01() throws IOException {
    
    
        fileSystem.copyFromLocalFile(new Path("D:\\2023PracticalTraining\\software\\InstallPackage\\PowerDesginer16.5.zip"),new Path("/demo"));
        System.out.println("上传成功!");
        //fileSystem.copyToLocalFile();
    }

    /**
     * 2、下载文件
     * 在Windows上远程操作HDFS或者是在Windows上操作MapReduce代码的时候,有些情况下要求windows上也必须有hadoop的软件环境
     * 但是hadoop只能在Linux上安装,因此,Windows上安装的hadoop其实是一个假的环境
     *  报错:exitcode=-107xxxxxxx 原因是因为电脑缺少C语言的运行环境
     */
    @Test
    public void test02() throws IOException {
    
    
        fileSystem.copyToLocalFile(new Path("/jdk-8u371-linux-x64.tar.gz"),new Path("D:\\Desktop"));
        System.out.println("下载成功!");
    }
    /**
     * 3、删除文件的方法
     */
    @Test
    public void test03() throws IOException {
    
    
        boolean delete = fileSystem.delete(new Path("/demo"), true);
        System.out.println(delete);
    }
}

テスト01:

画像-20230719180840341

画像-20230719180857446

テスト02:

エラー メッセージが表示されます: HADOOP_HOME と hadoop.home.dir が設定されていません。

Windows 上で HDFS をリモートで操作する場合、または Windows 上で MapReduce コードを操作する場合、場合によっては、Windows にも Hadoop ソフトウェア環境が必要になります。

ただし、Hadoop は Linux にしかインストールできないため、Windows にインストールされた Hadoop は実際には偽の環境です。

まず、Linux に送信された hadoop-3.1.4.tar.gz インストール パッケージを hadoop-3.1.4.tar に解凍し、次に hadoop-3.1.4 に解凍します。

解凍時にエラーが報告されますが、このエラーは無視されます。

解凍後、ファイル内の bin ディレクトリ内のすべてのファイルを置き換えます。置き換えたファイルは、Baidu で検索してダウンロードできます。

環境変数を構成する

画像-20230719183149170

システム変数のパスを編集する

画像-20230719183209057

プログラムを再度実行すると成功します。

画像-20230719181854392

テスト03:

画像-20230719183529104

画像-20230719183541369

package com.kang;

import org.apache.hadoop.conf.Configuration;
import org.apache.hadoop.fs.FileStatus;
import org.apache.hadoop.fs.FileSystem;
import org.apache.hadoop.fs.Path;

import java.io.IOException;
import java.net.URI;
import java.net.URISyntaxException;

/**
 * hdfs查看某个路径下的所有文件和文件夹的信息
 */
public class Demo01 {
    
    
    public static void main(String[] args) throws URISyntaxException, IOException, InterruptedException {
    
    
        Configuration conf = new Configuration();
        FileSystem fs = FileSystem.get(new URI("hdfs://192.168.31.104:9000"), conf, "root");

        /**
         *
         */
        FileStatus[] fileStatuses = fs.listStatus(new Path("/"));
        for (FileStatus fileStatus : fileStatuses) {
    
    
            System.out.println(fileStatus.getPath());
            System.out.println(fileStatus.getBlockSize());
            System.out.println(fileStatus.getPermission());
            System.out.println(fileStatus.getOwner());
            System.out.println(fileStatus.getGroup());
        }

    }
}

画像-20230719214637916

package com.kang;

import org.apache.hadoop.conf.Configuration;
import org.apache.hadoop.fs.FileSystem;
import org.apache.hadoop.fs.Path;

import java.io.IOException;
import java.net.URI;
import java.net.URISyntaxException;

/**
 * hdfs的相关判断类型的JavaAPI操作
 */
public class Demo02 {
    
    
    public static void main(String[] args) throws URISyntaxException, IOException, InterruptedException {
    
    
        Configuration conf = new Configuration();
        FileSystem fs = FileSystem.get(new URI("hdfs://192.168.31.104:9000"), conf, "root");

        boolean b = fs.isDirectory(new Path("/demo"));
        System.out.println(b);
        boolean b1 = fs.isFile(new Path("/demo"));
        System.out.println(b1);
        boolean exists = fs.exists(new Path("/a"));
        System.out.println(exists);

    }
}
package com.kang;

import org.apache.hadoop.conf.Configuration;
import org.apache.hadoop.fs.FileSystem;
import org.apache.hadoop.fs.Path;

import java.io.IOException;
import java.net.URI;
import java.net.URISyntaxException;

/**
 * hdfs的创建相关的JavaAPI
 */
public class Demo03 {
    
    
    public static void main(String[] args) throws URISyntaxException, IOException, InterruptedException {
    
    
        Configuration conf = new Configuration();
        FileSystem fs = FileSystem.get(new URI("hdfs://192.168.31.104:9000"), conf, "root");

        boolean mkdirs = fs.mkdirs(new Path("/a/b"));
        System.out.println(mkdirs);

        boolean newFile = fs.createNewFile(new Path("/a/a.txt"));
        System.out.println(newFile);

    }
}
package com.kang;

import org.apache.hadoop.conf.Configuration;
import org.apache.hadoop.fs.FSDataInputStream;
import org.apache.hadoop.fs.FileSystem;
import org.apache.hadoop.fs.Path;

import java.io.FileOutputStream;
import java.io.IOException;
import java.net.URI;
import java.net.URISyntaxException;

/**
 * hdfs提供了一个可以借助JavaIO流读取数据的方法
 *  上传fs.create		下载fs.open
 */
public class Demo04 {
    
    
    public static void main(String[] args) throws URISyntaxException, IOException, InterruptedException {
    
    
        Configuration conf = new Configuration();
        FileSystem fs = FileSystem.get(new URI("hdfs://192.168.31.104:9000"), conf, "root");

        FSDataInputStream inputStream = fs.open(new Path("/jdk-8u371-linux-x64.tar.gz"));
        inputStream.seek(128*1024*1024);
        FileOutputStream fos = new FileOutputStream("D:\\Desktop\\block2");
        int read = 0;
        while((read = inputStream.read())!=-1){
    
    
            fos.write(read);
        }
        System.out.println("第二个数据块读取完成");
    }
}
  • HDFS は、多数の小さなファイルの定数には適しておらず、HDFS は保存されたファイルを変更できません。

3. HDFS ワークフローの問題 (HDFS の主要な内容)

1. HDFSアップロードデータ処理

客户端在和DN建立连接的时候,是和距离它最近的某一个DN建立连接
怎么判断DN距离客户端的距离:网络拓扑原则
客户端和HDFS的节点在同一个集群上

  • クライアントは namenode にファイルのアップロードを要求し、namenode はターゲット ファイルが既に存在するかどうか、および親ディレクトリが存在するかどうかを確認します。
  • namenode はアップロードできるかどうかを返します。
  • クライアントが最初のブロックのアップロードを要求するデータノード サーバー。
  • namenode は 3 つのデータノード ノード、つまり dn1、dn2、および dn3 を返します。
  • クライアントは dn1 にデータのアップロードを要求します。dn1 が要求を受信すると、引き続き dn2 を呼び出し、次に dn2 が dn3 を呼び出して、この通信パイプラインの確立を完了します。
  • dn1、dn2、および dn3 はクライアントに段階的に応答します。
  • クライアントは、最初のブロックを dn1 にアップロードし始めます (最初にディスクからデータを読み取り、ローカル メモリ キャッシュに置きます)。パケット単位では、dn1 がパケットを受信すると、それは dn2 に渡され、dn2 に渡されます。 dn3 に; dn1 が 1 を渡すたびに、パケットは応答を待つ応答キューに置かれます。
  • ブロック転送が完了すると、クライアントは再度ネームノードに 2 番目のブロックをサーバーにアップロードするよう要求します。(手順 3 ~ 7 を繰り返します)

2. HDFSダウンロードデータ処理

  • クライアントはネームノードにファイルのダウンロードを要求し、ネームノードはメタデータを照会することによってファイル ブロックが配置されているデータノード アドレスを見つけます。
  • データノード (最も近い原則、次にランダム) サーバーを選択し、データの読み取りを要求します。
  • データノードは、クライアントへのデータの送信を開始します (ディスクからデータを読み取り、ストリームに入れ、パケットで検証します)。
  • クライアントはパケットをパケット単位で受信し、ローカルにキャッシュして、ターゲット ファイルに書き込みます。

3. HDFSコピーバックアップメカニズム

数据上传的时候,会根据配置进行block块的备份,备份的时候,选择哪些节点进行数据备份?
机架感知原则进行备份

低バージョンの Hadoop レプリカ ノードの選択:

第一个副本在client所处的节点上。如果客户端在集群外,随机选一个。
第二个副本和第一个副本位于不相同机架的随机节点上。
第三个副本和第二个副本位于相同机架,节点随机。

Hadoop2.8.5 レプリカ ノードの選択:

第一个副本在client所处的节点上。如果客户端在集群外,随机选一个。
第二个副本和第一个副本位于相同机架,随机节点。
第三个副本位于不同机架,随机节点。

4. HDFS における NameNode と SecondaryNameNode の動作メカニズム

この動作メカニズムは、NameNode がメタデータを管理する方法です。

メタデータ: HDFS ストレージ ファイル/フォルダーの同様のディレクトリ構造を指します。ディレクトリには、各ファイルのサイズ、時間、ブロック数、およびブロックに格納されているノード リスト情報が記録されます... NameNode のデフォルト メタデータ メモリは 1000M
です、数百万ブロックのメタデータ情報を保存および管理できます。

メタデータに関連する 2 つのファイル - HDFS の再起動後にメタデータを復元するメカニズム

edits 編集ログ ファイル: HDFS クラスターへのクライアントの書き込みおよび変更操作を記録します。

fsimage イメージ ファイル: HDFS メタデータの永続的なポイント チェック ファイルとして理解されます。

HDFS セーフ モード(セーフモード)

HDFS が起動すると、まずセーフ モードに入ります。セーフ モードとは、編集ファイルと fsimage ファイルが nn メモリにロードされる期間、および dn が NN に登録される期間です。

HDFS クラスターをセーフ モードで動作できない場合、セーフ モードは自動的に終了し、NN メモリがロードされ (メタデータがロードされ)、HDFS クラスターは開始するノード数を満たしたままになります。

SNN の機能は、NN 上でチェックポイント (チェックポイント メカニズム) 操作を実行することです。

  • チェックポイントはいつトリガーされますか?

    • チェックポイント時間が経過しました - 1 時間
      dfs.namenode.checkpoint.period 3600s
    • 最後のチェックポイント操作以降、 HDFS は 100 万
      dfs.namenode.checkpoint.txns 1000000に達しました。
  • SNN は 1 分ごとに NN に checkponit 操作を実行するかどうかを尋ねます
    dfs.namenode.checkpoint.check.period 60s

NameNode の障害後にメタデータを回復する方法

  • メタデータの中核は編集ファイルと fsimage ファイルであり、SNN が動作している場合、nn ファイルが SNN にコピーされるため、NN のメタデータが失われた場合、これらのファイルを SNN から NN のディレクトリにコピーできます。メタデータのリカバリ (リカバリによりメタデータの一部が失われる可能性があります)
    SNN ディレクトリ: hadoop . tmp . dir / dfs / namesecondary / currentnn ディレクトリ: {hadoop.tmp.dir}/dfs/namesecondary/current nn ディレクトリ:ha doo p . t m p . dir / df s / nam eseco nd ary / currentディレクトリ: { hadoop.tmp.dir } / dfs / name / current _


  • メタデータを復元する別の方法があります: 複数のディレクトリに保存するように HDFS ネームノードを構成します (HDFS 編集ログとミラー ファイルは同じバックアップを複数のディレクトリに保存します)。この方法は同じノード
    のみ使用できます。問題: ノード全体ががダウンすると、
    dfs.namenode.name.dir への複数のパスを復元できません。

    hdfs-site.xml
    <property>
      <name>dfs.namenode.name.dir</name>
    <value>/opt/app/hadoop/data/dfs/name1,/opt/app/hadoop/data/dfs/name2</value>
    </property>
    
  • HDFS を再フォーマットするか、ディレクトリを手動で作成することをお勧めします。

  • HA高可用性モード

5. HDFS における NameNode と DataNode の間の動作メカニズム

  • 詳細なプロセス
    • データ ブロックは、データノード上のファイルの形式でディスクに保存されます。このファイルには 2 つのファイルが含まれます。1 つはデータ自体で、もう 1 つはデータ ブロックの長さ、ブロック データのチェックサム、およびタイムスタンプ。
    • DataNode は起動後、namenode に登録し、登録完了後、定期的 (1 時間) にすべてのブロック情報を namenode に報告します。
    • ハートビートは 3 秒に 1 回で、ハートビートの戻り結果には、ブロック データを別のマシンにコピーする、または特定のデータ ブロックを削除するなど、ネームノードからデータノードに与えられるコマンドが含まれます。データノードのハートビートが 10 分以上受信されない場合、そのノードは使用できないとみなされます。
    • 一部のマシンは、クラスターの実行中に安全に追加および終了できます。

データ自体に加えて、DataNode に保存されるブロックには、データの長さ、データのチェックサム、タイムスタンプなども含まれます。

データ チェックサムは、ブロックの整合性と一貫性を保証するものです。チェックサム メカニズムはチェックサムです。ブロックが作成されると、データ自体に基づいてチェックサムが計算されます。将来的には、DN が作成されるたびにチェックサムが再度実行されます。ブロック サマリーを実行します。チェックサムの計算で、2 つのチェックサムが一致しない場合、ブロックは破損していると見なされます。

DataNode および NameNode のハートビート、デフォルトのハートビートは 3 秒に 1 回、デフォルト値は調整可能
dfs.heartbeat.interval 3s

<property>
  <name>dfs.namenode.heartbeat.recheck-interval</name>
  <value>300000</value>单位毫秒
</property>
<property>
  <name> dfs.heartbeat.interval </name>
  <value>3</value>单位秒
</property>

この構成を変更する場合、HDFS を閉じる必要がありますが、再フォーマットは必要ありません。
ハートビートには 2 つの機能があります: 1. DN が生きているかどうかを検出するため。 2. NN が DN に要求したことを DN に伝えるため。

NN は、DN がオフライン、デッド、ダウン (切断の時間制限) であることをどのようにして認識しますか: NN が特定のハートビート内で DN のハートビートを受信しない場合、NN は DN が停止しているとは考えず、ビートを続けます。は、オフライン時間制限内にハートビートが成功する前に DN が無効であるとみなして、バックアップ回復メカニズムを開始します。オフライン時間制限の長さの計算式は次のとおりです:
timeout
= 2 * dfs.namenode.heartbeat.recheck-interval + 10 * dfs.heartbeat.interval。
dfs.namenode.heartbeat.recheck-interval ハートビート検出時間 5 分
dfs.heartbeat.interval ハートビート時間 3 秒
デフォルトでは、DN からのハートビートが 10 分 30 秒を超えて受信されない場合、DN は停止しているとみなされます。

DataNode はノード上のすべてのブロックのブロック情報を 6 時間ごとに NameNode に報告します (デフォルトは 6 時間)
dfs.blockreport.intervalMsec 21600000ms DN ブロック情報を 6 時間ごとに NN に報告します
dfs.datanode.directoryscan.interval 21600s DN がブロックをスキャンしますDN に関する情報は 6 時間ごとに提供されます。

4. HDFS および YARN の新しいノードのサービスと古いノードの廃止 - namenode が配置されているノードの Hadoop で構成する

1.コンセプト

HDFS は分散ファイル ストレージ システムです。ビッグ データ ソフトウェアとして、HDFS は基本的に 24 時間年中無休です。HDFS クラスターの容量が十分でない場合、HDFS を停止できないため、新しいデータ ノードを追加する必要があります。そのため、HDFS クラスターの操作中にデータ ノード (新しいノードのサービス操作) を動的に追加し、古いノードを廃止する必要があります。

2. 新ノードサービス運用

新しいノードを提供する前に、新しい仮想ノードを作成し、Java、Hadoop 環境、SSH パスワード不要のログイン、IP、ホスト マッピング、およびホスト名を構成する必要があります。

1. Hadoop 構成ファイルのディレクトリに dfs.hosts ファイルを作成し、そのファイル内で Hadoop クラスターのスレーブ ノードのホスト名を宣言します。

2. Hadoop の hdfs-site.xml ファイルに、構成項目
dfs.hosts 値: ファイルのパスを追加します。

<!--dfs.hosts代表改文件中的地址都为白名单,可以访问NameNode节点,与NameNode节点通信-->
<property>
  <name>dfs.hosts</name>
  <value>/opt/app/hadoop-3.1.4/etc/hadoop/dfs.hosts</value>
</property>

3. HDFS がオンになっている場合、スレーブ ノード情報
hdfs dfsadmin -refreshNodesyarn
rmadmin -refreshNodesを更新します。

4. ノード サービスを正常に実装するには、新しいノードで datanode と nodemanager を起動するだけです。

hadoop-daemon.sh データノードを開始します

hadoop-daemon.sh ノードマネージャーを起動します

3. 古いノードの廃止 (初めて廃止ファイルを追加する場合は、HDFS クラスターを再起動する必要があります)

1. Hadoop 構成ディレクトリにファイル dfs.hosts.exclude を作成し、そのファイルに廃止されたホスト名を書き込みます。


2. Hadoop の hdfs-site.xml 構成ファイルで、廃止されたノード ファイルdfs.hosts.exclude 値ファイルのパスを宣言します。

<!--dfs.hosts.exculde文件代表namenode访问的黑名单  需要退役的数据节点
黑名单加入的数据节点如果也在dfs.hosts文件存在的话  不会立即退出 而是先把数据块转移到其他数据节点 然后再退役
-->
<property>
  <name>dfs.hosts.exclude</name>
  <value>/opt/app/hadoop-3.1.4/etc/hadoop/dfs.hosts.exclude</value>
</property>

3. 同時に、dfs.hosts のサービス ノード ファイル内の廃止されたノードを削除する必要があります。

4. ノード情報ステータスの更新
hdfs dfsadmin -refreshNodesyarn
rmadmin -refreshNodes

[注意] 廃止時には、廃止されたノードのブロックが廃止されていないノードにコピーされ、その後オフラインになります。コピー数以上です。

おすすめ

転載: blog.csdn.net/weixin_57367513/article/details/132715434