Zookeeper - 分散サービス調整フレームワーク

1. Zookeeperの概要

1. Zookeeperの基本概念

  • Zookeeper は、分散アプリケーションの調整サービスを提供するオープンソースの分散 Apache プロジェクトです。
  • Zookeeper をデザイン パターンの観点から理解すると、オブザーバー パターンに基づいて設計された分散サービス管理フレームワークであり、誰もが関心を持つデータの保存と管理を担当し、オブザーバーの登録を受け付けます。データ変更、Zookeeper Zookeeper に登録されているオブザーバーに、それに応じて対応するように通知する役割を果たします。これにより、クラスター内で同様のマスター/スレーブ管理モデルが実現されます。
  • Zookeeper = ファイル システム + 通知メカニズム

2. Zookeeperの特徴

  • 動物園の飼育員: リーダーと信者の集団。
  • リーダーは、投票の開始と決定、およびシステム ステータスの更新を担当します。
  • フォロワーは、顧客のリクエストを受信して​​結果をクライアントに返し、リーダーの選出時の投票に参加するために使用されます。
  • グループ内のノードの半分以上が存続している限り、Zookeeper クラスターは正常に機能します。
  • グローバル データの一貫性: 各サーバーは同じデータのコピーを保存するため、クライアントがどのサーバーに接続しても、データは一貫しています。
  • 更新リクエストは順番に実行され、同じクライアントからの更新リクエストは送信された順に順番に実行されます。
  • データ更新はアトミックであり、データ更新は成功するか失敗します。
  • クライアントは、特定の時間範囲内でリアルタイムに最新のデータを読み取ることができます。

3. Zookeeperのデータ構造

  • ZooKeeper データ モデルの構造は Unix ファイル システムに非常に似ており、全体としてツリーとみなすことができ、各ノードは ZNode と呼ばれます。
  • Zookeeper クラスター自体は、一連のデータ構造を維持します。このストレージ構造はツリー構造であり、その上の各ノードは「znode」と呼ばれます。ツリーのノードとは異なり、Znode 参照メソッドはファイル パス: /znode1/leaf1 と同様のパス参照です。
  • このような階層構造により、各 Znode ノードが一意のパスを持つことができ、名前空間と同様に異なる情報を明確に分離できます。
  • ZooKeeper ノードはツリー状の構造を通じて維持され、各ノードにはマークが付けられ、パスを通じてアクセスされます。
  • さらに、各ノードには、データ、データ長、作成時間、変更時間などの独自の情報もあります。
  • データを含み、パス テーブルとしてマークされているこのようなノードの特性から、ZooKeeper ノードはファイルまたはディレクトリのいずれかとみなすことができ、両方の特性を備えていることがわかります。表現を容易にするため、将来的には、問題の ZooKeeper ノードを表すために Znode を使用する予定です。
  • 各 znode はデフォルトで1MBのデータを保存できます
  • znode はクライアントによって作成されます。znode を作成したクライアントとの本質的な関係によって、znode の存在が決まります。通常、ノードには次の 4 つのタイプがあります。
    • PERSISTENT - 永続ノード: このノードを作成したクライアントが Zookeeper サービスから切断した後、このノードは削除されません (API を使用して強制的に削除されない限り)
    • PERSISTENT_SEQUENTIAL - 永続的な連続番号ノード: クライアントがこのノード A の作成を要求すると、zookeeper は親 znode の zxid ステータスに基づいて、この A ノードにディレクトリ全体で一意の番号を書き込みます (この番号は増加し続けるだけです)。クライアントが Zookeeper サービスから切断されても、ノードは削除されません。
    • EPHEMERAL-一時ディレクトリ ノード: このノードを作成したクライアントが Zookeeper サービスから切断されると、このノード (および関連する子ノード) は削除されます。
    • EPHEMERAL_SEQUENTIAL - 一時的な連続番号ディレクトリ ノード: クライアントがこのノード A の作成を要求すると、zookeeper は親 znode の zxid ステータスに基づいて、この A ノードにディレクトリ全体で一意の番号を書き込みます (この番号は増加し続けるだけです)。ノードを作成したクライアントが Zookeeper サービスから切断すると、ノードは削除されます。
    • [注意] : EPHEMERAL または EPHEMERAL_SEQUENTIAL ノード タイプに関係なく、Zookeeper クライアントが異常終了した後、ノードも削除されます。

2. Zookeeper のインストールと展開

1. Zookeeperをダウンロード

Zookeeper の公式 Web サイトで、ダウンロードする必要があるバージョンを選択します。以下は私がダウンロードしたバージョンです。

画像-20230914153823247

画像-20230914154058193

2. Zookeeperのインストール

ローカル モード (スタンドアロン モード) でのインストールと展開

ステップ 1: ダウンロードした圧縮パッケージを仮想マシンの指定されたディレクトリにアップロードします。私は /opt/software/ にアップロードしました。

ステップ 2: 圧縮パッケージを指定したディレクトリに解凍します。私は /opt/app/ に解凍しました。

tar -zxvf apache-zookeeper-3.8.2-bin.tar.gz -C /opt/app/

ステップ 3: Zookeeper フォルダーの名前を変更する

mv apache-zookeeper-3.8.2-bin/ zookeeper-3.8.2

ステップ 4: 環境変数を構成し、構成ファイルをソースして有効にする

vim /etc/profile source /etc/profile

画像-20230914154523937

ステップ 5:/opt/app/zookeeper-3.8.2/confディレクトリに入り、構成ファイルの名前を変更しmv zoo_sample.cfg zoo.cfg、編集します。/opt/app/zookeeper-3.8.2/新しいディレクトリを作成しますtouch zkData

画像-20230914154730291

ステップ6: コマンドを使用してzkServer.sh startzookeeperを起動し、 コマンドを使用してzkServer.sh statuszookeeperのステータスを確認し、 コマンドを使用してnetstat -untlpポート番号を確認します。

画像-20230914154925015

画像-20230914155004720

ステップ7: コマンドを使用してzkCli.sh -server localhost:2181クライアントに入ります

画像-20230914155112299

ステップ8:コマンドを使用してzkServer.sh stop終了する

画像-20230914155154497

分散 (クラスター モード クラスター) のインストールと展開

  • クラスター計画

    • 在node1、node2、node3三个节点上部署Zookeeper。
      
  • まず、解凍してインストールするノード 1 ノードを選択します。手順はローカル モードのインストールと展開と同じです。

  • 設定ファイルzoo.cfgを変更します。

[root@node1 software]# vim /opt/app/zookeeper/conf/zoo.cfg
#修改dataDir数据目录
dataDir=/opt/module/zookeeper-3.8.2/zkData
#在文件最后增加如下配置
server.1=node1:2888:3888
server.2=node2:2888:3888
server.3=node3:2888:3888

server.A=B:C:D。
A是一个数字,表示这个是第几号服务器;
B是这个服务器的ip地址;
C是这个服务器与集群中的Leader服务器交换信息的端口;
D是万一集群中的Leader服务器挂了,需要一个端口来重新进行选举,选出一个新的Leader,而这个端口就是用来执行选举时服务器相互通信的端口。
集群模式下配置一个文件myid,这个文件在dataDir目录下,这个文件里面有一个数据就是A的值,Zookeeper启动时读取此文件,拿到里面的数据与zoo.cfg里面的配置信息比较从而判断到底是哪个server。

画像-20230914165158962

  • の下に/opt/app/zookeeper-3.8.2フォルダーを作成し、このディレクトリに入り、現在のホストの番号を定義するmkdir zkDataファイルを作成します。touch myid
#在配置zoo.cfg的时候配置了server.1/2/3这个配置项中  数字123代表的就是第几号服务器
#其中这个数字必须在zookeeper的zkData的myid文件中定义  并且定义的时候必须和配置项对应的IP相互匹配
[root@node1 zookeeper]# touch /opt/app/zookeeper/zkData/myid
[root@node1 zookeeper]# vim /opt/app/zookeeper/zkData/myid
#文件中写入当前主机对应的数字 然后保存退出即可 例 node1节点的myid写入1   node2节点的myid写入:2   node3节点的myid写入:3

画像-20230914170134011

  • 構成されたZookeeperを他のマシンにコピーする

    scp -r /opt/app/zookeeper-3.8.2/ root@node2:/opt/app/
    scp -r /opt/app/zookeeper-3.8.2/ root@node3:/opt/app/
    并分别修改myid文件中内容为2、3
    

画像-20230914202418214

  • ノード 2 およびノー​​ド 3 で、zookeeper に必要な環境変数を構成します。

画像-20230914202607865

  • 別途Zookeeperを起動してステータスを確認する

画像-20230914203152616

3. 飼育員の内部実装原則

1. 選出の仕組み

  • ハーフメカニズム (Paxos プロトコル): クラスター内のマシンの半分以上が存続し、クラスターは使用可能です。したがって、Zookeeper は奇数のマシンへのインストールに適しています。
  • ただし、Zookeeper は設定ファイルでマスターとスレーブを指定しません。ただし、Zookeeper が動作する場合、1 つのノードがリーダーとなり、他のノードはフォロワーとなり、リーダーは内部選挙メカニズムを通じて一時的に生成されます。

1. Zookeeper を初めて起動するときの選出メカニズム

  • 動物園飼育員の内部選出メカニズム

    • 5 台のサーバーで構成される Zookeeper クラスターがあるとします。その ID の範囲は 1 から 5 です。同時に、それらはすべて新しく開始されたものです。つまり、履歴データはありません。保存されているデータの量は同じです。これらのサーバーが順番に起動されると仮定すると、内部実装プロセスは次の図のようになります。

      画像

      • サーバー 1 が起動されます。この時点では、サーバーは 1 つだけ起動されます。送信されたレポートに対する応答がないため、その選出ステータスは常に LOOKING 状態になります。
      • サーバー 2 が起動します。最初に起動したサーバー 1 と通信し、お互いの選出結果を交換します。どちらも履歴データを持っていないため、ID 値が大きいサーバー 2 が勝ちますが、ID 値が大きいサーバー 2 が勝ちます。サーバーは選択に同意するに達していないため (この例では半数以上が 3 です)、サーバー 1 と 2 は LOOKING 状態を維持し続けます。
      • サーバー 3 が起動します。先ほどの理論分析によれば、サーバー 3 はサーバー 1、2、3 の中でリーダーになります。上記との違いは、この時点で 3 つのサーバーが選出したため、今回の選出のリーダーになることです。
      • サーバー 4 が起動されます。前の分析によると、理論的にはサーバー 4 はサーバー 1、2、3、4 の中で最大であるはずです。しかし、以前のサーバーの半数以上がサーバー 3 を選択しているため、サーバー 3 は命令しか受け取ることができません。弟であるということ。
      • サーバー 5 が起動し、サーバー 4 と同様に弟として機能します。

2. 初めて起動しないときの飼育員の選出メカニズム

  • SID: サーバーID。ZooKeeper クラスター内のマシンを一意に識別するために使用されます。各マシンは重複できず、myid と一貫性があります。
  • ZXID: トランザクション ID。ZXID は、サーバーの状態の変化を識別するために使用されるトランザクション ID です。ある時点では、クラスター内の各マシンの ZXID 値がまったく同じではない可能性がありますが、これは、クライアントの「更新リクエスト」に対する ZooKeeper サーバーの処理ロジックに関連しています。
  • エポック: 各リーダー用語のコード名。リーダーが存在しない場合、同じ投票ラウンドの論理クロック値は同じになります。このデータは投票が行われるたびに増加します。

zk選挙

2. Zookeeper のデータ書き込みプロセス

1. リーダーノードを直接記述するプロセス

書き込みリーダー

2. Followerの処理を直接記述する

フォロワーを書く

3. データ書き込み処理の詳細概要

  • たとえば、クライアントは ZooKeeper の Server1 にデータを書き込み、書き込みリクエストを送信します。
  • Server1 がリーダーではない場合、各 ZooKeeper サーバーの 1 つがリーダーであるため、Server1 は受信したリクエストをリーダーにさらに転送します。リーダーは書き込みリクエストを Server1 や Server2 などの各サーバーにブロードキャストします。成功するとリーダーに通知されます。
  • リーダーがサーバー データの大部分を受信して​​正常に書き込むと、データが正常に書き込まれたことになります。ここにノードが 3 つある場合、2 つのノードのデータが正常に書き込まれていれば、データは正常に書き込まれたとみなされます。書き込みが成功すると、リーダーは Server1 にデータの書き込みが成功したことを伝えます。
  • さらに、Server1 はデータが正常に書き込まれたことをクライアントに通知し、書き込み操作全体が成功したとみなされます。ZooKeeperのデータ書き込み処理全体はこんな感じです。

4. Zookeeper クライアントのコマンドライン操作

  • コマンドを使用して、Zookeeper クラスターに接続します。zkCli.sh -server node:2181,node2:2181,node3:2181

1. コマンドライン構文

基本的なコマンド構文 機能説明
ヘルプ すべての操作コマンドを表示
ls パス [監視] ls コマンドを使用して、現在の znode に含まれるコンテンツを表示します。
ls -s パス [監視] 現在のノード情報の表示
作成 [-e] [-s] シーケンス -e でノード -s を作成する (タイムアウト後に再起動または消滅)
パスを取得 [監視] ノードの値を取得する
セット ノードの特定の値を設定します
ステータス ノードのステータスを表示する
消去 ノードの削除
RMR/削除オール ノードを再帰的に削除する

2. 基本的なコマンドライン操作

  1. コマンドラインクライアントを起動する

    zkCli.sh -server node1:2181,node2:2181,node3:2181
    

    画像-20230917155449174

  2. すべての操作コマンドを表示

    help
    

    画像-20230917155652051

    画像-20230917155719895

  3. znode ノード情報の表示

    ls / 
    

    画像-20230917155526869

  4. znode のノードに関する詳細情報を表示する

    [zk: node1:2181(CONNECTED) 5] ls -s / 
    [zookeeper]cZxid = 0x0 
    ctime = Thu Jan 01 08:00:00 CST 1970 
    mZxid = 0x0 
    mtime = Thu Jan 01 08:00:00 CST 1970 
    pZxid = 0x0 
    cversion = -1 
    dataVersion = 0 
    aclVersion = 0 
    ephemeralOwner = 0x0 
    dataLength = 0 
    numChildren = 1 
    
     (1)czxid:创建节点的事务 zxid 每次修改 ZooKeeper 状态都会产生一个 ZooKeeper 事务 ID。事务 ID 是 ZooKeeper 中所 有修改总的次序。每次修改都有唯一的 zxid,如果 zxid1 小于 zxid2,那么 zxid1 在 zxid2 之前发生。 
     (2)ctime:znode 被创建的毫秒数(从 1970 年开始) 
     (3)mzxid:znode 最后更新的事务 zxid 
     (4)mtime:znode 最后修改的毫秒数(从 1970 年开始) 
     (5)pZxid:znode 最后更新的子节点 zxid
     (6)cversion:znode 子节点变化号,znode 子节点修改次数 
     (7)dataversion:znode 数据变化号 
     (8)aclVersion:znode 访问控制列表的变化号 
     (9)ephemeralOwner:如果是临时节点,这个是 znode 拥有者的 session id。如果不是 临时节点则是 0。 
     (10)dataLength:znode 的数据长度 
     (11)numChildren:znode 子节点数量
    
  5. 通常ノード(永続ノード+シリアル番号なし)の作成

    create /sanguo "weishuwu"
    

    画像-20230917160623571

  6. ノードの値を取得する

    get -s /test 
    
  7. シリアル番号付きノードの作成 (永続ノード + シリアル番号付き)

    create  -s  /a
    
    create  -s  /a 
    
    create  /a 
    
    如果原来没有序号节点,序号从 0 开始依次递增。如果原节点下已有 2 个节点,则再排序时从 2 开始,以此类推。
    

    画像-20230917161532151

  8. 一時ノードの作成 (エフェメラル ノード + シリアル番号なしまたはシリアル番号あり)

     (1)创建短暂的不带序号的节点 
    create -e /b
    
     (2)创建短暂的带序号的节点 
    create -e -s /b
    
     (3)在当前客户端是能查看到的 
    ls /
    
     (4)退出当前客户端然后再重启客户端 
     [zk: node1:2181(CONNECTED) 12] quit 
     [root@node1 zookeeper-3.5.7]$ bin/zkCli.sh 
     (5)再次查看根目录下短暂节点已经删除 
    ls /
    

    画像-20230917161824546

    画像-20230917161947604

  9. ノードデータ値を変更する

    [zk: node1:2181(CONNECTED) 6] set /sanguo/weiguo "simayi"
    
  10. ノードの削除

    delete /test
    
  11. ノードを再帰的に削除する

    deleteall /test
    

    画像-20230917161321106

  12. ノードのステータスを表示する

    stat /sanguo 
    

    画像-20230917160608475

    13. ノードのデータ変更を監視する

    get -w /sanguo
    

    14. ノードの子ノードの変更をリッスンする

    ls -w /sanguo
    

    画像-20230917161125996

5. 高可用性HA-Hadoopクラスタの構築

1. 高可用性 HA の概要

  • いわゆる HA (高可用性) は、高可用性 (7*24 時間中断のないサービス) を意味します。
  • 高可用性を実現するための最も重要な戦略は、単一障害点を排除することです。厳密に言うと、HA はコンポーネントごとに HDFS HA と YARN HA の HA メカニズムに分割する必要があります。
  • Hadoop2.0 より前では、NameNode には HDFS クラスター内に単一障害点 (SPOF) がありました。
  • NameNode は、主に次の 2 つの側面で HDFS クラスターに影響を与えます。
    • NameNode マシンにダウンタイムなどの事故が発生した場合、管理者が再起動するまでクラスターは使用できなくなります。
    • NameNode マシンはソフトウェアとハ​​ードウェアのアップグレードを含めてアップグレードする必要があり、現時点ではクラスターは使用できません。
  • HDFS HA 機能は、Active/Standby の 2 つの NameNode を構成し、クラスター内の NameNode のホット バックアップを実装することで、上記の問題を解決します。マシンのクラッシュなどの障害が発生した場合、またはマシンのアップグレードとメンテナンスが必要な場合は、この方法で NameNode を別のマシンにすぐに切り替えることができます。

2. HDFS-HA 動作メカニズム: デュアル ネームノードを通じて単一障害点を排除します。

  • HDFS-HA 作業点

    • メタデータの管理方法を変更する必要がある(SecondaryNameNodeは不要)

      内存中各自保存一份元数据;
      Edits日志只有Active状态的namenode节点可以做写操作;
      两个namenode都可以读取edits;
      共享的edits放在一个共享存储中管理(qjournal和NFS两个主流实现);
      
    • ステータス管理機能モジュールが必要です

      实现了一个zkfailover,常驻在每一个namenode所在的节点,每一个zkfailover负责监控自己所在namenode节点,利用zk进行状态标识,当需要进行状态切换时,由zkfailover来负责切换,切换时需要防止brain split现象的发生。
      
    • 2 つのネームノード間で SSH パスワードなしのログインが可能であることを確認する必要があります。

    • 分離 (フェンス) とは、1 つの NameNode だけが同時に外部サービスを提供することを意味します。

3. HDFS-HAクラスタ構成

  • 環境の準備:

    • IPの変更

    • ホスト名と、ホスト名とIPアドレス間のマッピングを変更します。

    • ファイアウォールをオフにする

    • ssh パスワード不要のログイン

    • JDKのインストール、環境変数の設定などを行います。

  • クラスターの計画

ノード1 ノード2 ノード3
名前ノード 名前ノード -
ジャーナルノード ジャーナルノード ジャーナルノード
データノード データノード データノード
ZK ZK ZK
リソースマネージャー
ノードマネージャー ノードマネージャー ノードマネージャー
  • Zookeeper クラスターの構成: 上記のメモにすでに記録されています。

  • HDFS-HA クラスターを構成します。

    • hadoop-env.sh を構成する

      export JAVA_HOME=/opt/app/jdk
      
    • core-site.xmlを構成する

      <configuration>
      <!-- 把两个NameNode的地址组装成一个集群HadoopCluster -->
            <property>
                <name>fs.defaultFS</name>
                <value>hdfs://HC</value>
            </property>
            <!-- 指定hadoop运行时产生文件的存储目录 -->
            <property>
                <name>hadoop.tmp.dir</name>
                <value>/opt/app/hadoop-3.1.4/metaData</value>
            </property>
            <!--配置连接的zookeeper的地址-->
            <property>
                <name>ha.zookeeper.quorum</name>
                <value>node1:2181,node2:2181,node3:2181</value>
            </property>
      </configuration>
      

    画像-20230914213405059

    • hdfs-site.xml を構成する

      <configuration>
            <!-- 完全分布式集群名称 -->
        <property>
            <name>dfs.nameservices</name>
            <value>HC</value>
        </property>
        <!-- 集群中NameNode节点都有哪些 -->
        <property>
            <name>dfs.ha.namenodes.HC</name>
            <value>nn1,nn2</value>
        </property>
        <!-- nn1的RPC通信地址 -->
        <property>
            <name>dfs.namenode.rpc-address.HC.nn1</name>
            <value>node1:9000</value>
        </property>
        <!-- nn2的RPC通信地址 -->
        <property>
            <name>dfs.namenode.rpc-address.HC.nn2</name>
            <value>node2:9000</value>
        </property>
        <!-- nn1的http通信地址 -->
        <property>
            <name>dfs.namenode.http-address.HC.nn1</name>
            <value>node1:9870</value>
        </property>
        <!-- nn2的http通信地址 -->
        <property>
            <name>dfs.namenode.http-address.HC.nn2</name>
            <value>node2:9870</value>
        </property>
        <!-- 指定NameNode元数据在JournalNode上的存放位置 -->
        <property>
            <name>dfs.namenode.shared.edits.dir</name>
            <value>qjournal://node1:8485;node2:8485;node3:8485/HadoopCluster</value>
        </property>
        <!-- 配置隔离机制,即同一时刻只能有一台服务器对外响应 -->
        <property>
            <name>dfs.ha.fencing.methods</name>
            <value>sshfence</value>
        </property>
        <!-- 使用隔离机制时需要ssh无秘钥登录-->
        <property>
            <name>dfs.ha.fencing.ssh.private-key-files</name>
            <value>/root/.ssh/id_rsa</value>
        </property>
        <!-- 声明journalnode服务器存储目录-->
        <property>
            <name>dfs.journalnode.edits.dir</name>
            <value>/opt/app/hadoop-3.1.4/journalnodeData</value>
        </property>
        <!-- 关闭权限检查-->
        <property>
            <name>dfs.permissions.enable</name>
            <value>false</value>
        </property>
        <!-- 访问代理类:client,HadoopCluster,active配置失败自动切换实现方式-->
        <property>
              <name>dfs.client.failover.proxy.provider.HC</name>
            <value>org.apache.hadoop.hdfs.server.namenode.ha.ConfiguredFailoverProxyProvider</value>
        </property>
            <property>
                <name>dfs.replication</name>
                <value>3</value>
            </property>
            <property>
                <name>dfs.namenode.datanode.registration.ip-hostname-check</name>
                <value>true</value>
            </property>
          <property>
            <name>dfs.ha.automatic-failover.enabled</name>
            <value>true</value>
          </property>
       </configuration>
      
    • 構成されたHadoop環境を他のノードにコピーする

    scp /opt/app/hadoop-3.1.4/etc/hadoop/core-site.xml root@node2:/opt/app/hadoop-3.1.4/etc/hadoop/
    scp /opt/app/hadoop-3.1.4/etc/hadoop/core-site.xml root@node3:/opt/app/hadoop-3.1.4/etc/hadoop/
    scp /opt/app/hadoop-3.1.4/etc/hadoop/hdfs-site.xml root@node3:/opt/app/hadoop-3.1.4/etc/hadoop/
    scp /opt/app/hadoop-3.1.4/etc/hadoop/hdfs-site.xml root@node2:/opt/app/hadoop-3.1.4/etc/hadoop/
    
  • HDFS-HA クラスターの開始

    • psmisc ソフトウェアをインストールする

    zkfc の自動フェイルオーバーは psmisc ソフトウェアを使用して完了する必要があるため、このソフトウェアは 3 つのノードにインストールする必要があります。

    yum install -y psmisc
    

    画像-20230914231656221

    • 各 JournalNode ノードで次のコマンドを入力して、journalnode サービスを開始します。
      sbin/hadoop-daemon.sh start journalnode

    画像-20230914232428309

    • [nn1] でフォーマットして開始します。
      rm -rf metaData/ journalnodeData/  删除三台节点
     /opt/app/hadoop-3.1.4   hdfs namenode -format  只需要在第一台节点格式化
                             hadoop-daemon.sh start namenode    只需要执行一次即可,之后就不需要再执行
    
    • 図に示すように、エラーが発生しました

      • 画像-20230914233530301
      • vim /opt/app/hadoop-3.1.4/etc/hadoop/hadoop-env.sh画像-20230914233727627
      • scp /opt/app/hadoop-3.1.4/etc/hadoop/hadoop-env.sh root@node2:/opt/app/hadoop-3.1.4/etc/hadoop/
      • scp /opt/app/hadoop-3.1.4/etc/hadoop/hadoop-env.sh root@node3:/opt/app/hadoop-3.1.4/etc/hadoop/
      • 画像-20230914234007915
      • 起動するstart-dfs.sh
        • 画像-20230914234221142
    • [nn2] で、nn1 のメタデータ情報を同期します。
      bin/hdfs namenode -bootstrapStandbyこれは 1 回実行するだけで済み、再度実行する必要はありません。

      hadoop-daemon.sh start namenodeそして2番目のノードでnamenodeを開始します

    • 3 つのノードでデータノードを開始しますhadoop-daemon.sh start datanode

    • HDFSを再起動します

      • すべての HDFS サービスをシャットダウンします: sbin/stop-dfs.sh
      • Zookeeper クラスターを開始します: bin/zkServer.sh start
      • Zookeeper で HA ステータスを初期化します: bin/hdfs zkfc -formatZK
      • HDFS サービスを開始します: sbin/start-dfs.sh
      • 各 NameNode ノードで DFSZK フェイルオーバー コントローラーを開始します。どのマシンが最初に開始されますか? どのマシンの NameNode がアクティブな NameNode であるか: sbin/hadoop-daemin.sh start zkfc
    • 確認する

      • 画像-20230917171516996
      • 画像-20230917171551592
      • アクティブな NameNode プロセスを強制終了します:kill -9 namenode のプロセス ID
        • 画像-20230917171646083
      • アクティブなネームノード マシンをネットワークから切断します: サービス ネットワークの停止
        • 画像-20230917171634976

6. YARN-HA 構成

YARN-HA クラスターの構成

  • 環境整備
    • IPの変更
    • ホスト名と、ホスト名とIPアドレス間のマッピングを変更します。
    • ファイアウォールをオフにする
    • ssh パスワード不要のログイン
    • JDKのインストール、環境変数の設定などを行います。
    • Zookeeper クラスターの構成
  • クラスターの計画
ノード1 ノード2 ノード3
名前ノード 名前ノード
ジャーナルノード ジャーナルノード ジャーナルノード
データノード データノード データノード
ZK ZK ZK
リソースマネージャー リソースマネージャー
ノードマネージャー ノードマネージャー ノードマネージャー
  • 特定の構成 - 各ノードで構成します

    • 糸サイト.xml

      <configuration>
        <property>
            <name>yarn.nodemanager.aux-services</name>
            <value>mapreduce_shuffle</value>
        </property>
        <!--启用resourcemanager ha-->
        <property>
            <name>yarn.resourcemanager.ha.enabled</name>
            <value>true</value>
        </property>
        <!--声明两台resourcemanager的地址-->
        <property>
            <name>yarn.resourcemanager.cluster-id</name>
            <value>cluster-yarn1</value>
        </property>
        <property>
            <name>yarn.resourcemanager.ha.rm-ids</name>
            <value>rm1,rm2</value>
        </property>
        <property>
            <name>yarn.resourcemanager.hostname.rm1</name>
            <value>node1</value>
        </property>
        <property>
            <name>yarn.resourcemanager.hostname.rm2</name>
            <value>node2</value>
        </property>
        <!--指定zookeeper集群的地址--> 
        <property>
            <name>yarn.resourcemanager.zk-address</name>
            <value>node1:2181,node2:2181,node3:2181</value>
        </property>
        <!--启用自动恢复--> 
        <property>
            <name>yarn.resourcemanager.recovery.enabled</name>
            <value>true</value>
        </property>
        <!--指定resourcemanager的状态信息存储在zookeeper集群--> 
        <property>
            <name>yarn.resourcemanager.store.class</name>     
            <value>org.apache.hadoop.yarn.server.resourcemanager.recovery.ZKRMStateStore</value>
        </property>
      </configuration>
      
    • 他のノードの構成情報を同期して更新します

      • scp /opt/app/hadoop-3.1.4/etc/hadoop/yarn-site.xml root@node2:/opt/app/hadoop-3.1.4/etc/hadoop/
        scp /opt/app/hadoop-3.1.4/etc/hadoop/yarn-site.xml root@node3:/opt/app/hadoop-3.1.4/etc/hadoop/
        

        画像-20230917230055889

  • hdfs を開始します (HA-Hadoop クラスターを構築している場合は、この手順を実行する必要はありません)。

    • 各 JournalNode ノードで、次のコマンドを入力してジャーナルノード サービスを開始します: sbin/hadoop-daemon.sh startjournalnode

    • [nn1] でフォーマットして開始します。

      bin/hdfs namenode -format
      sbin/hadoop-daemon.sh start namenode
      
    • [nn2] で、nn1 のメタデータ情報を同期します: bin/hdfs namenode -bootstrapStandby

    • 開始 [nn2]: sbin/hadoop-daemon.sh 開始ネームノード

    • すべてのデータノードを開始します: sbin/hadoop-daemons.sh start datanode

    • [nn1] をアクティブに切り替えます: bin/hdfs haadmin -transitionToActive nn1

  • 糸を始める

    • ノード1で実行: sbin/start-yarn.sh
    • ノード2で実行: sbin/yarn-daemon.sh start resourcemanager
    • サービスのステータスを確認します: bin/yarn rmadmin -getServiceState rm1

画像-20230917230905317

画像-20230917231006420

7. MR プログラムを使用して高可用性環境で単語を数える方法

wc.txtを編集してhdfsにアップロードします

画像-20230918092044257

画像-20230918092053070

アイデアを開き、Maven プロジェクトを作成し、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>ha-test</artifactId>
  <version>1.0</version>
  <packaging>jar</packaging>

  <name>ha-test</name>
  <url>http://maven.apache.org</url>

  <properties>
    <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
  </properties>

  <dependencies>
    <dependency>
      <groupId>org.apache.hadoop</groupId>
      <artifactId>hadoop-client</artifactId>
      <version>3.1.4</version>
    </dependency>
    <dependency>
      <groupId>org.apache.hadoop</groupId>
      <artifactId>hadoop-hdfs</artifactId>
      <version>3.1.4</version>
    </dependency>
    <dependency>
      <groupId>org.slf4j</groupId>
      <artifactId>slf4j-log4j12</artifactId>
      <version>1.6.1</version>
    </dependency>
  </dependencies>
</project>

MapReduce コードの作成

画像-20230918112525372

package com.kang;

import org.apache.hadoop.io.LongWritable;
import org.apache.hadoop.io.Text;
import org.apache.hadoop.mapreduce.Mapper;

import java.io.IOException;

public class WCMapper extends Mapper<LongWritable, Text,Text,LongWritable> {
    
    
    @Override
    protected void map(LongWritable key, Text value, Mapper<LongWritable, Text, Text, LongWritable>.Context context) throws IOException, InterruptedException {
    
    
        String line = value.toString();
        String[] words = line.split(" ");
        for (String word : words) {
    
    
            context.write(new Text(word),new LongWritable(1L));
        }
    }
}


package com.kang;

import org.apache.hadoop.io.LongWritable;
import org.apache.hadoop.io.Text;
import org.apache.hadoop.mapreduce.Reducer;

import java.io.IOException;

public class WCReduce extends Reducer<Text, LongWritable,Text,LongWritable> {
    
    
    @Override
    protected void reduce(Text key, Iterable<LongWritable> values, Reducer<Text, LongWritable, Text, LongWritable>.Context context) throws IOException, InterruptedException {
    
    
        long sum = 0L;
        for (LongWritable value : values) {
    
    
            sum += value.get();
        }
        context.write(key,new LongWritable(sum));
    }
}



package com.kang;

import org.apache.hadoop.conf.Configuration;
import org.apache.hadoop.fs.Path;
import org.apache.hadoop.io.LongWritable;
import org.apache.hadoop.mapreduce.Job;
import org.apache.hadoop.mapreduce.lib.input.FileInputFormat;
import org.apache.hadoop.mapreduce.lib.output.FileOutputFormat;

import javax.xml.soap.Text;
import java.io.IOException;

public class WCDriver {
    
    
    public static void main(String[] args) throws IOException, InterruptedException, ClassNotFoundException {
    
    
        Configuration conf = new Configuration();
        conf.set("fs.defaultFS","hdfs://HC");

        Job job = Job.getInstance(conf);
        job.setJarByClass(WCDriver.class);
        FileInputFormat.setInputPaths(job,new Path("/wc.txt"));

        job.setMapperClass(WCMapper.class);
        job.setMapOutputKeyClass(Text.class);
        job.setMapOutputValueClass(LongWritable.class);

        job.setReducerClass(WCReduce.class);
        job.setOutputKeyClass(Text.class);
        job.setOutputValueClass(LongWritable.class);
        job.setNumReduceTasks(0);

        FileOutputFormat.setOutputPath(job,new Path("/output"));

        boolean flag = job.waitForCompletion(true);
        System.exit(flag?0:1);
    }
}

hdfs-site.xml と core-site.xml を仮想マシンから Java プロジェクト ディレクトリにエクスポートします。

画像-20230918112631575

次に、WCDriver を実行すると、アクセス許可が不十分であるというエラー メッセージが表示されますので、このタスクを達成するためにアクセス許可を変更します。

画像-20230918112748878

画像-20230918112901312

プログラムを再度実行すると、コード 0 が返されます。これは、操作が成功したことを意味します。

画像-20230918112950486

画像-20230918113032239

最後に、Hadoop 分散ファイル システム (HDFS) 内のファイルとディレクトリのデフォルトのアクセス許可をデフォルトのアクセス許可の種類に復元します。

画像-20230918113342735

おすすめ

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