動物園飼育員の分散型信頼性の高い調整システム

1. 動物園飼育員について知る

公式 Web サイトのアドレス: https://zookeeper.apache.org/
Zookeeper は、分散アプリケーションの調整サービスを提供するオープンソースの分散 Apache プロジェクトです。

Zookeeper = ファイル システム + 通信メカニズム (動作メカニズム: オブザーバー モード)
特点:
  1)Zookeeper:一个领导者(Leader),多个跟随者(Follower)组成的集群。
  2)集群中只要有半数以上节点存活,Zookeeper集群就能正常服务。
  3)全局数据一致:每个Server保存一份相同的数据副本,Client无论连接到哪个Server,数据都是一致的。
  4)更新请求顺序进行,来自同一个Client的更新请求按其发送顺序依次执行。
  5)数据更新原子性,一次数据更新要么成功,要么失败。
  6)实时性,在一定时间范围内,Client能读到最新数据。

アプリケーションシナリオ:

  • 統一ネーミングサービス
  • 統合構成管理
  • 統合クラスター管理
  • サーバーノードは動的にオンラインとオフラインになります
  • ソフトロードバランシング

選出メカニズム:

  • 半分のメカニズム: クラスター内のマシンの半分以上が存続し、クラスターは使用可能です。したがって、Zookeeper は奇数のサーバーをインストールするのに適しています。
  • ただし、Zookeeper は設定ファイルで Leader と Follower を指定しません。ただし、Zookeeper が動作しているときは、1 つのノードがリーダーとなり、他のノードはフォロワーとなり、リーダーは内部選挙メカニズムを通じて一時的に生成されます。
(1)服务器1启动,发起一次选举。服务器1投自己一票,此时服务器1票数一票,不够半数以上(3票),选举无法完成,服务器1状态保持为LOOKING;

(2)服务器2启动,再发起一次选举。服务器1和2分别投自己一票并交换选票信息,此时服务器1发现服务器2的ID比自己目前投票推举的(服务器1)大,则更改选票为推举服务器2,此时服务器1票数0票,服务器2票数2票,没有半数以上结果,选举无法完成,服务器1,2状态保持LOOKING;

(3)服务器3启动,发起一次选举。此时服务器1和2都会更改选票为服务器3,此次投票结果:服务器1为0票,服务器2为0票,服务器3为3票,此时服务器3的票数已经超过半数,服务器3当选Leader。服务器1,2更改状态为FOLLOWING,服务器3更改状态为LEADING;

(4)服务器4启动,发起一次选举。此时服务器1,2,3已经不是LOOKING状态,不会更改选票信息,交换选票信息结果:服务器3为3票,服务器4为1票。此时服务器4服从多数,更改选票信息为服务器3,并更改状态为FOLLOWING;

(5)服务器5启动,于4的过程一样,更改选票信息为服务器3,并更改状态为FOLLOWING。

小结:投票选举的过程与mtime-znode最后修改时间和配置id有关,先会找最后修改的Server当Leader,若一样,则会找配置id大的。

ノードタイプ:
ここに画像の説明を挿入します

リスナーの原則:
ここに画像の説明を挿入します

データ書き込みプロセス:
ここに画像の説明を挿入します

2. ローカル モード インストール (Windows システムを例にとると、Linux インストールと同じです)

1. JDKがインストールされていることを確認したら、公式Webサイトからインストールパッケージをダウンロードし、指定したディレクトリに解凍します。
2. 構成の変更。

将conf路径下的zoo_sample.cfg修改为zoo.cfg

打开zoo.cfg文件,修改dataDir路径。(路径可以自己设置,方便查看,别忘记创建设置的文件夹)
dataDir=../data

3. Zookeeperを操作する

windows直接执行bin目录下的zkServer.cmd启动服务端,执行zkCli.cmd启动客户端

linux
  启动服务端:bin/zkServer.sh start
  查看启动状态:bin/zkServer.sh status
  启动客户端:bin/zkCli.sh

3. 分散インストール (Linux を例にします)

1. 公式 Web サイトから圧縮パッケージをダウンロードし、指定したディレクトリに解凍します。

tar -zxvf zookeeper-3.4.10.tar.gz -C /opt/module/

2. コンテンツを他のサーバーと同期します。

xsync zookeeper-3.4.10/

3. サーバー番号を設定します。

/opt/module/zookeeper-3.4.10/目录下创建zkData:
mkdir -p zkData

在zkData目录下创建一个myid文件:
touch myid
vi myid
添加与server对应的编号:2

拷贝配置好的zookeeper到其他机器上(注意修改编号,确保唯一):
xsync myid

4.zoo.cfgファイルを設定する

mv zoo_sample.cfg zoo.cfg
vi zoo.cfg
修改数据存储路径配置:
dataDir=/opt/module/zookeeper-3.4.10/zkData

增加如下配置:
#####################cluster############################
server.2=hadoop102:2888:3888
server.3=hadoop103:2888:3888
server.4=hadoop104:2888:3888

サーバー (サーバー番号) = (サーバーの IP アドレス): (サーバーとクラスター内のリーダー サーバーの間で情報を交換するためのポート): (選挙中にサーバーが相互に通信するためのポート)

4. シェルコマンドの操作

(1) 全ての動作コマンドを表示します。

help

(2) 現在の znode に含まれるコンテンツを表示します。

ls /

(3) 現在のノードの詳細データを表示します。

ls2 /

(4) 通常のノードを作成します。

create /ceshi "ceshi"

(5) ノードの値を取得します。

get /ceshi

(6) 有効期間の短いノードを作成します。

create -e /ceshi "ceshi"

(7) シリアル番号を付けてノードを作成します。(シーケンス番号ノードが元々存在しない場合、シーケンス番号は 0 から始まり、順番に増加します。元のノードの下に既に 2 つのノードがある場合、並べ替えは 2 から始まります。以下同様)

create -s /ceshi "ceshi"

(8) ノードデータの値を変更します。

set /ceshi "ceshi"

(9) ノード値の変化を監視します。

get /ceshi watch

(10)ノードの子ノードの変化(パス変化)を監視する。

ls /ceshi watch

(11) ノードを削除します。

delete /ceshi 

(12) ノードを再帰的に削除します。

rmr /ceshi 

(13) ノードの状態を確認します。

stat /ceshi 

5. コードの実装

1. 依存関係を導入する

 <dependencies>
    <dependency>
      <groupId>junit</groupId>
      <artifactId>junit</artifactId>
      <version>4.11</version>
      <scope>test</scope>
    </dependency>
    <dependency>
      <groupId>log4j</groupId>
      <artifactId>log4j</artifactId>
      <version>1.2.12</version>
    </dependency>
    
    <!--zookeeper依赖-->
    <dependency>
      <groupId>org.apache.zookeeper</groupId>
      <artifactId>zookeeper</artifactId>
      <version>3.7.0</version>
    </dependency>
  </dependencies>

2. ログ構成ファイルを追加し、
プロジェクトのリソース ディレクトリに新しい log4j.properties ファイルを作成します。

log4j.rootLogger=INFO,stdout
log4j.appender.stdout=org.apache.log4j.ConsoleAppender
log4j.appender.stdout.layout=org.apache.log4j.PatternLayout
log4j.appender.stdout.layout.ConversionPattern=%d %p [%c] - %m%n
log4j.appender.logfile=org.apache.log4j.FileAppender
log4j.appender.logfile.File=target/spring.log
log4j.appender.logfile.layout=org.apache.log4j.PatternLayout
log4j.appender.logfile.layout.conversionPattern=%d %p [%c] - %m%n

3. ZookeeperTest テスト クラスを作成します。

package com.yzs;

import org.apache.zookeeper.*;
import org.apache.zookeeper.data.Stat;
import org.junit.Before;
import org.junit.Test;

import java.io.IOException;
import java.util.List;

public class ZookeeperTest {
    
    
    private String connectString = "127.0.0.1:2181";
    private int sessionTimeout = 2000;
    private ZooKeeper zooKeeper;

    //连接zookeeper服务端
    @Before
    public void connectZookeeper() throws IOException {
    
    
        zooKeeper = new ZooKeeper(connectString, sessionTimeout, new Watcher() {
    
    
            @Override
            public void process(WatchedEvent watchedEvent) {
    
    
                List<String> children = null;
                try {
    
    
                    children = zooKeeper.getChildren("/", true);
                    for (String child : children){
    
    
                        System.out.println(child);
                    }
                } catch (KeeperException e) {
    
    
                    e.printStackTrace();
                } catch (InterruptedException e) {
    
    
                    e.printStackTrace();
                }
            }
        });
    }

    //创建子节点
    @Test
    public void createNode() throws KeeperException, InterruptedException {
    
    
        zooKeeper.create("/sanguo","sanguo".getBytes(), ZooDefs.Ids.OPEN_ACL_UNSAFE,CreateMode.PERSISTENT);
    }

    //获取子节点并监听数据变化
    @Test
    public void getChildrenAndWatch() throws KeeperException, InterruptedException {
    
    
        List<String> children = zooKeeper.getChildren("/", true);
        for (String child : children){
    
    
            System.out.println(child);
        }
        //延时阻塞
        Thread.sleep(Long.MAX_VALUE);
    }

    //判断是否存在节点
    @Test
    public void exist() throws KeeperException, InterruptedException {
    
    
        Stat stat = zooKeeper.exists("/sanguo", false);
        System.out.println(stat == null?"not exist":"exist");
    }

    //获取节点上的数据
    @Test
    public void getNode() throws KeeperException, InterruptedException {
    
    
        byte[] data = zooKeeper.getData("/sanguo", false, null);
        System.out.println(new String(data));
    }
}

おすすめ

転載: blog.csdn.net/fish332/article/details/118156605