10_大數(shù)據(jù)之Zookeeper

Zookeeper入門

1??概述
??Zookeeper是一個(gè)開源的分布式的,為分布式應(yīng)用提供協(xié)調(diào)服務(wù)的Apache項(xiàng)目。

2??特點(diǎn)

3??數(shù)據(jù)結(jié)構(gòu)

4??應(yīng)用場景 : 提供的服務(wù)包括:統(tǒng)一命名服務(wù)、統(tǒng)一配置管理、統(tǒng)一集群管理、服務(wù)器節(jié)點(diǎn)動(dòng)態(tài)上下線、軟負(fù)載均衡等。
統(tǒng)一命名服務(wù)
統(tǒng)一配置管理
統(tǒng)一集群管理
服務(wù)器節(jié)點(diǎn)動(dòng)態(tài)上下線
軟負(fù)載均衡

5??下載地址
?官網(wǎng)首頁:https://zookeeper.apache.org/


Zookeeper的安裝

1??本地模式安裝部署
1.安裝前準(zhǔn)備
(1)安裝Jdk
(2)拷貝Zookeeper安裝包到Linux系統(tǒng)下
(3)解壓到指定目錄 tar -zxvf zookeeper-3.4.10.tar.gz -C /opt/module/
2.配置修改
(1)將/opt/module/zookeeper-3.4.10/conf這個(gè)路徑下的zoo_sample.cfg修改為zoo.cfg; mv zoo_sample.cfg zoo.cfg
(2)打開zoo.cfg文件,修改dataDir路徑:vim zoo.cfg
?修改如下內(nèi)容:dataDir=/opt/module/zookeeper-3.4.10/zkData
(3)在/opt/module/zookeeper-3.4.10/這個(gè)目錄上創(chuàng)建zkData文件夾;mkdir zkData
3.操作Zookeeper
(1)啟動(dòng)Zookeeper; bin/zkServer.sh start
(2)查看進(jìn)程是否啟動(dòng); jps
(3)查看狀態(tài):bin/zkServer.sh status
(4)啟動(dòng)客戶端:bin/zkCli.sh
(5)退出客戶端:quit
(6)停止Zookeeper : bin/zkServer.sh stop

2??配置參數(shù)解讀 : Zookeeper中的配置文件zoo.cfg中參數(shù)含義解讀如下.
?1.tickTime =2000:通信心跳數(shù),Zookeeper服務(wù)器與客戶端心跳時(shí)間,單位毫秒Zookeeper使用的基本時(shí)間,服務(wù)器之間或客戶端與服務(wù)器之間維持心跳的時(shí)間間隔,也就是每個(gè)tickTime時(shí)間就會(huì)發(fā)送一個(gè)心跳,時(shí)間單位為毫秒。它用于心跳機(jī)制,并且設(shè)置最小的session超時(shí)時(shí)間為兩倍心跳時(shí)間。(session的最小超時(shí)時(shí)間是2*tickTime)
?2.initLimit =10LF初始通信時(shí)限集群中的Follower跟隨者服務(wù)器與Leader領(lǐng)導(dǎo)者服務(wù)器之間初始連接時(shí)能容忍的最多心跳數(shù)(tickTime的數(shù)量),用它來限定集群中的Zookeeper服務(wù)器連接到Leader的時(shí)限。
?3.syncLimit =5LF同步通信時(shí)限集群中LeaderFollower之間的最大響應(yīng)時(shí)間單位,假如響應(yīng)超過syncLimit * tickTime,Leader認(rèn)為Follwer死掉,從服務(wù)器列表中刪除Follwer
?4.dataDir:數(shù)據(jù)文件目錄+數(shù)據(jù)持久化路徑主要用于保存Zookeeper中的數(shù)據(jù)。
?5.clientPort =2181:客戶端連接端口監(jiān)聽客戶端連接的端口。


Zookeeper實(shí)戰(zhàn)

1??分布式安裝部署
1.集群規(guī)劃 : 在hadoop102hadoop103hadoop104三個(gè)節(jié)點(diǎn)上部署Zookeeper。
2.解壓安裝
(1)解壓Zookeeper安裝包到/opt/module/目錄下 : tar -zxvf zookeeper-3.4.10.tar.gz -C /opt/module/
(2)同步/opt/module/zookeeper-3.4.10目錄內(nèi)容到hadoop103、hadoop104 : xsync zookeeper-3.4.10/
3.配置服務(wù)器編號
(1)在/opt/module/zookeeper-3.4.10/這個(gè)目錄下創(chuàng)建zkData : mkdir -p zkData
(2)在/opt/module/zookeeper-3.4.10/zkData目錄下創(chuàng)建一個(gè)myid的文件touch myid添加myid文件,注意一定要在linux里面創(chuàng)建,外部創(chuàng)建很可能會(huì)亂碼
(3)編輯myid文件 : vi myid 在文件中添加與server對應(yīng)的編號2
(4)拷貝配置好的zookeeper到其他機(jī)器上 : xsync myid,并分別在hadoop103、hadoop104上修改myid文件中內(nèi)容為3、4;
4.配置zoo.cfg文件
(1)重命名/opt/module/zookeeper-3.4.10/conf這個(gè)目錄下的zoo_sample.cfgzoo.cfg : mv zoo_sample.cfg zoo.cfg
(2)打開zoo.cfg文件 : vim zoo.cfg 修改數(shù)據(jù)存儲(chǔ)路徑配置dataDir=/opt/module/zookeeper-3.4.10/zkData增加如下配置

#######################cluster##########################
server.2=hadoop102:2888:3888
server.3=hadoop103:2888:3888
server.4=hadoop104:2888:3888

(3)同步zoo.cfg配置文件 : xsync zoo.cfg
(4)配置參數(shù)解讀 : server.A=B:C:D
A是一個(gè)數(shù)字,表示這個(gè)是第幾號服務(wù)器;集群模式下配置一個(gè)文件myid,這個(gè)文件在dataDir目錄下,這個(gè)文件里面有一個(gè)數(shù)據(jù)就是A的值,Zookeeper啟動(dòng)時(shí)讀取此文件,拿到里面的數(shù)據(jù)與zoo.cfg里面的配置信息比較從而判斷到底是哪個(gè)server
B是這個(gè)服務(wù)器的地址;
C是這個(gè)服務(wù)器Follower與集群中的Leader服務(wù)器交換信息的端口;
D是萬一集群中的Leader服務(wù)器掛了,需要一個(gè)端口來重新進(jìn)行選舉,選出一個(gè)新的Leader,而這個(gè)端口就是用來執(zhí)行選舉時(shí)服務(wù)器相互通信的端口。

  1. 集群操作
    (1)分別啟動(dòng)Zookeeper;bin/zkServer.sh start
    (2)查看狀態(tài);bin/zkServer.sh status

2??客戶端命令行操作

1.啟動(dòng)客戶端 : bin/zkCli.sh
2.顯示所有操作命令 : help
3.查看當(dāng)前znode中所包含的內(nèi)容 : ls /
4.查看當(dāng)前節(jié)點(diǎn)詳細(xì)數(shù)據(jù) : 'ls2 /'
5.分別創(chuàng)建2個(gè)普通節(jié)點(diǎn) : create /sanguo "jinlian", create /sanguo/shuguo "liubei"
6.獲得節(jié)點(diǎn)的值 : get /sanguo
7.創(chuàng)建短暫節(jié)點(diǎn) : create -e /sanguo/wuguo "zhouyu"
(1)在當(dāng)前客戶端是能查看到的 : ls /sanguo
(2)退出當(dāng)前客戶端然后再重啟客戶端 : quit, bin/zkCli.sh
(3)再次查看根目錄下短暫節(jié)點(diǎn)已經(jīng)刪除 : ls /sanguo
8.創(chuàng)建帶序號的節(jié)點(diǎn)
(1)先創(chuàng)建一個(gè)普通的根節(jié)點(diǎn)/sanguo/weiguo : create /sanguo/weiguo "caocao"
(2)創(chuàng)建帶序號的節(jié)點(diǎn) :

create -s /sanguo/weiguo/xiaoqiao "jinlian"
create -s /sanguo/weiguo/daqiao "jinlian"
create -s /sanguo/weiguo/diaocan "jinlian"

?如果原來沒有序號節(jié)點(diǎn),序號從0開始依次遞增。如果原節(jié)點(diǎn)下已有2個(gè)節(jié)點(diǎn),則再排序時(shí)從2開始,以此類推。
9.修改節(jié)點(diǎn)數(shù)據(jù)值 : set /sanguo/weiguo "simayi"
10.節(jié)點(diǎn)的值變化監(jiān)聽
(1)在hadoop104主機(jī)上注冊監(jiān)聽/sanguo節(jié)點(diǎn)數(shù)據(jù)變化 : get /sanguo watch
(2)在hadoop103主機(jī)上修改/sanguo節(jié)點(diǎn)的數(shù)據(jù) : set /sanguo "xisi"
(3)觀察hadoop104主機(jī)收到數(shù)據(jù)變化的監(jiān)聽

WATCHER::
WatchedEvent state:SyncConnected type:NodeDataChanged path:/sanguo

11.節(jié)點(diǎn)的子節(jié)點(diǎn)變化監(jiān)聽(路徑變化)
(1)在hadoop104主機(jī)上注冊監(jiān)聽/sanguo節(jié)點(diǎn)的子節(jié)點(diǎn)變化 : ls /sanguo watch
(2)在hadoop103主機(jī)/sanguo節(jié)點(diǎn)上創(chuàng)建子節(jié)點(diǎn)
create /sanguo/jin "simayi"
(3)觀察hadoop104主機(jī)收到子節(jié)點(diǎn)變化的監(jiān)聽

WATCHER::
WatchedEvent state:SyncConnected type:NodeChildrenChanged path:/sanguo

12.刪除節(jié)點(diǎn) : delete /sanguo/jin
13.遞歸刪除節(jié)點(diǎn) : rmr /sanguo/shuguo
14.查看節(jié)點(diǎn)狀態(tài) : stat /sanguo

3??API應(yīng)用
1.創(chuàng)建一個(gè)Maven工程
2.添加pom文件

<dependencies>
       <dependency>
           <groupId>junit</groupId>
           <artifactId>junit</artifactId>
           <version>RELEASE</version>
       </dependency>
       <dependency>
           <groupId>org.apache.logging.log4j</groupId>
           <artifactId>log4j-core</artifactId>
           <version>2.8.2</version>
       </dependency>
       <!-- https://mvnrepository.com/artifact/org.apache.zookeeper/zookeeper -->
       <dependency>
           <groupId>org.apache.zookeeper</groupId>
           <artifactId>zookeeper</artifactId>
           <version>3.4.10</version>
       </dependency>
</dependencies>

3.拷貝log4j.properties文件到項(xiàng)目根目錄 : 需要在項(xiàng)目的src/main/resources目錄下,新建一個(gè)文件,命名為“l(fā)og4j.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
  1. 創(chuàng)建ZooKeeper客戶端
private static String connectString = "hadoop102:2181,hadoop103:2181,hadoop104:2181";
private static int sessionTimeout = 2000;
private ZooKeeper zkClient = null;
@Before
public void init() throws Exception {
zkClient = new ZooKeeper(connectString, sessionTimeout, new Watcher() {
       @Override
       public void process(WatchedEvent event) {
           // 收到事件通知后的回調(diào)函數(shù)(用戶的業(yè)務(wù)邏輯)
           System.out.println(event.getType() + "--" + event.getPath());
           // 再次啟動(dòng)監(jiān)聽
           try {
               zkClient.getChildren("/", true);
           } catch (Exception e) {
               e.printStackTrace();
           }
       }
   });
  1. 創(chuàng)建子節(jié)點(diǎn)
// 創(chuàng)建子節(jié)點(diǎn)
@Test
public void create() throws Exception {

       // 參數(shù)1:要?jiǎng)?chuàng)建的節(jié)點(diǎn)的路徑; 參數(shù)2:節(jié)點(diǎn)數(shù)據(jù) ; 參數(shù)3:節(jié)點(diǎn)權(quán)限 ;參數(shù)4:節(jié)點(diǎn)的類型
       String nodeCreated = zkClient.create("/xxx", "jinlian".getBytes(), Ids.OPEN_ACL_UNSAFE, CreateMode.PERSISTENT);
}
  1. 獲取子節(jié)點(diǎn)并監(jiān)聽節(jié)點(diǎn)變化
// 獲取子節(jié)點(diǎn)
@Test
public void getChildren() throws Exception {

       List<String> children = zkClient.getChildren("/", true);

       for (String child : children) {
           System.out.println(child);
       }

       // 延時(shí)阻塞
       Thread.sleep(Long.MAX_VALUE);
}
  1. 判斷Znode是否存在
// 判斷znode是否存在
@Test
public void exist() throws Exception {

   Stat stat = zkClient.exists("/eclipse", false);

   System.out.println(stat == null ? "not exist" : "exist");
}

4?? 監(jiān)聽服務(wù)器節(jié)點(diǎn)動(dòng)態(tài)上下線案例(擴(kuò)展)
1.需求 : 某分布式系統(tǒng)中,主節(jié)點(diǎn)可以有多臺(tái),可以動(dòng)態(tài)上下線,任意一臺(tái)客戶端都能實(shí)時(shí)感知到主節(jié)點(diǎn)服務(wù)器的上下線。
2.需求分析

3.具體實(shí)現(xiàn)
(1)先在集群上創(chuàng)建/servers節(jié)點(diǎn) : create /servers "servers";
(2)服務(wù)器端向Zookeeper注冊代碼

package com.xxx.zkcase;
import java.io.IOException;
import org.apache.zookeeper.CreateMode;
import org.apache.zookeeper.WatchedEvent;
import org.apache.zookeeper.Watcher;
import org.apache.zookeeper.ZooKeeper;
import org.apache.zookeeper.ZooDefs.Ids;

public class DistributeServer {

   private static String connectString = "hadoop102:2181,hadoop103:2181,hadoop104:2181";
   private static int sessionTimeout = 2000;
   private ZooKeeper zk = null;
   private String parentNode = "/servers";
   
   // 創(chuàng)建到zk的客戶端連接
   public void getConnect() throws IOException{
       
       zk = new ZooKeeper(connectString, sessionTimeout, new Watcher() {

           @Override
           public void process(WatchedEvent event) {

           }
       });
   }
   
   // 注冊服務(wù)器
   public void registServer(String hostname) throws Exception{

       String create = zk.create(parentNode + "/server", hostname.getBytes(), Ids.OPEN_ACL_UNSAFE, CreateMode.EPHEMERAL_SEQUENTIAL);
       
       System.out.println(hostname +" is online "+ create);
   }
   
   // 業(yè)務(wù)功能
   public void business(String hostname) throws Exception{
       System.out.println(hostname+" is working ...");
       
       Thread.sleep(Long.MAX_VALUE);
   }
   
   public static void main(String[] args) throws Exception {
       
// 1獲取zk連接
       DistributeServer server = new DistributeServer();
       server.getConnect();
       
       // 2 利用zk連接注冊服務(wù)器信息
       server.registServer(args[0]);
       
       // 3 啟動(dòng)業(yè)務(wù)功能
       server.business(args[0]);
   }
}

(3)客戶端代碼

package com.xxx.zkcase;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
import org.apache.zookeeper.WatchedEvent;
import org.apache.zookeeper.Watcher;
import org.apache.zookeeper.ZooKeeper;

public class DistributeClient {

   private static String connectString = "hadoop102:2181,hadoop103:2181,hadoop104:2181";
   private static int sessionTimeout = 2000;
   private ZooKeeper zk = null;
   private String parentNode = "/servers";

   // 創(chuàng)建到zk的客戶端連接
   public void getConnect() throws IOException {
       zk = new ZooKeeper(connectString, sessionTimeout, new Watcher() {

           @Override
           public void process(WatchedEvent event) {

               // 再次啟動(dòng)監(jiān)聽
               try {
                   getServerList();
               } catch (Exception e) {
                   e.printStackTrace();
               }
           }
       });
   }

   // 獲取服務(wù)器列表信息
   public void getServerList() throws Exception {
       
       // 1獲取服務(wù)器子節(jié)點(diǎn)信息,并且對父節(jié)點(diǎn)進(jìn)行監(jiān)聽
       List<String> children = zk.getChildren(parentNode, true);

       // 2存儲(chǔ)服務(wù)器信息列表
       ArrayList<String> servers = new ArrayList<>();
       
       // 3遍歷所有節(jié)點(diǎn),獲取節(jié)點(diǎn)中的主機(jī)名稱信息
       for (String child : children) {
           byte[] data = zk.getData(parentNode + "/" + child, false, null);

           servers.add(new String(data));
       }

       // 4打印服務(wù)器列表信息
       System.out.println(servers);
   }

   // 業(yè)務(wù)功能
   public void business() throws Exception{

       System.out.println("client is working ...");
Thread.sleep(Long.MAX_VALUE);
   }

   public static void main(String[] args) throws Exception {

       // 1獲取zk連接
       DistributeClient client = new DistributeClient();
       client.getConnect();

       // 2獲取servers的子節(jié)點(diǎn)信息,從中獲取服務(wù)器信息列表
       client.getServerList();

       // 3業(yè)務(wù)進(jìn)程啟動(dòng)
       client.business();
   }
}

Zookeeper內(nèi)部原理

1??節(jié)點(diǎn)類型

2??Stat結(jié)構(gòu)體
1)czxid-創(chuàng)建節(jié)點(diǎn)的事務(wù)zxid
?每次修改ZooKeeper狀態(tài)都會(huì)收到一個(gè)zxid形式的時(shí)間戳,也就是ZooKeeper事務(wù)ID
?事務(wù)IDZooKeeper中所有修改總的次序。每個(gè)修改都有唯一的zxid,如果zxid1小于zxid2,那么zxid1zxid2之前發(fā)生。
2)ctime - znode被創(chuàng)建的毫秒數(shù)(從1970年開始)
3)mzxid - znode最后更新的事務(wù)zxid
4)mtime - znode最后修改的毫秒數(shù)(從1970年開始)
5)pZxid-znode最后更新的子節(jié)點(diǎn)zxid
6)cversion - znode子節(jié)點(diǎn)變化號,znode子節(jié)點(diǎn)修改次數(shù)
7)dataversion - znode數(shù)據(jù)變化號
8)aclVersion - znode訪問控制列表的變化號
9)ephemeralOwner- 如果是臨時(shí)節(jié)點(diǎn),這個(gè)是znode擁有者的session id。如果不是臨時(shí)節(jié)點(diǎn)則是0。
10)dataLength- znode的數(shù)據(jù)長度
11)numChildren - znode子節(jié)點(diǎn)數(shù)量

3??監(jiān)聽器原理(面試重點(diǎn))

4??Paxos算法(擴(kuò)展)
??Paxos算法一種基于消息傳遞且具有高度容錯(cuò)特性的一致性算法。
??分布式系統(tǒng)中的節(jié)點(diǎn)通信存在兩種模型:共享內(nèi)存(Shared memory)和消息傳遞(Messages passing)?;谙鬟f通信模型的分布式系統(tǒng),不可避免的會(huì)發(fā)生以下錯(cuò)誤:進(jìn)程可能會(huì)慢、被殺死或者重啟,消息可能會(huì)延遲、丟失、重復(fù),在基礎(chǔ) Paxos場景中,先不考慮可能出現(xiàn)消息篡改即拜占庭錯(cuò)誤的情況。Paxos算法解決的問題是在一個(gè)可能發(fā)生上述異常的分布式系統(tǒng)中如何就某個(gè)值達(dá)成一致,保證不論發(fā)生以上任何異常,都不會(huì)破壞決議的一致性。

Paxos算法流程中的每條消息描述如下:
1.Prepare: Proposer生成全局唯一且遞增的Proposal ID (可使用時(shí)間戳加Server ID),向所有Acceptors發(fā)送Prepare請求,這里無需攜帶提案內(nèi)容,只攜帶Proposal ID即可。
2.Promise: Acceptors收到Prepare請求后,做出“兩個(gè)承諾,一個(gè)應(yīng)答”。
兩個(gè)承諾:
a.不再接受Proposal ID小于等于(注意:這里是<= )當(dāng)前請求的Prepare請求。
b.不再接受Proposal ID小于(注意:這里是<)當(dāng)前請求的Propose請求。
一個(gè)應(yīng)答:
c.不違背以前做出的承諾下,回復(fù)已經(jīng)Accept過的提案中Proposal ID最大的那個(gè)提案的ValueProposal ID,沒有則返回空值。
3.Propose: Proposer 收到多數(shù)AcceptorsPromise應(yīng)答后,從應(yīng)答中選擇Proposal ID最大的提案的Value,作為本次要發(fā)起的提案。如果所有應(yīng)答的提案Value均為空值,則可以自己隨意決定提案Value。然后攜帶當(dāng)前Proposal ID,向所有Acceptors發(fā)送Propose請求。
4.Accept: Acceptor收到Propose請求后,在不違背自己之前做出的承諾下,接受并持久化當(dāng)前Proposal ID和提案Value。
5.Learn: Proposer收到多數(shù)AcceptorsAccept后,決議形成,將形成的決議發(fā)送給所有Learners。
下面我們針對上述描述做三種情況的推演舉例:為了簡化流程,我們這里不設(shè)置Learner。
情況1
情況2
??Paxos算法缺陷:在網(wǎng)絡(luò)復(fù)雜的情況下,一個(gè)應(yīng)用Paxos算法的分布式系統(tǒng),可能很久無法收斂,甚至陷入活鎖的情況。
情況3
??造成這種情況的原因是系統(tǒng)中有一個(gè)以上的Proposer,多個(gè)Proposers相互爭奪Acceptors,造成遲遲無法達(dá)成一致的情況。針對這種情況,一種改進(jìn)的Paxos算法被提出:從系統(tǒng)中選出一個(gè)節(jié)點(diǎn)作為Leader,只有Leader能夠發(fā)起提案。這樣,一次Paxos流程中只有一個(gè)Proposer,不會(huì)出現(xiàn)活鎖的情況,此時(shí)只會(huì)出現(xiàn)例子中第一種情況。

5??選舉機(jī)制
1)半數(shù)機(jī)制:集群中半數(shù)以上機(jī)器存活,集群可用。所以Zookeeper適合安裝奇數(shù)臺(tái)服務(wù)器。
2)Zookeeper雖然在配置文件中并沒有指定MasterSlave。但是,Zookeeper工作時(shí),是有一個(gè)節(jié)點(diǎn)為Leader,其他則為Follower,Leader是通過內(nèi)部的選舉機(jī)制臨時(shí)產(chǎn)生的。
3)以一個(gè)簡單的例子來說明整個(gè)選舉的過程。
??假設(shè)有五臺(tái)服務(wù)器組成的Zookeeper集群,它們的id1-5,同時(shí)它們都是最新啟動(dòng)的,也就是沒有歷史數(shù)據(jù),在存放數(shù)據(jù)量這一點(diǎn)上,都是一樣的。假設(shè)這些服務(wù)器依序啟動(dòng),來看看會(huì)發(fā)生什么,如下圖所示。

(1)服務(wù)器1啟動(dòng),發(fā)起一次選舉。服務(wù)器1投自己一票。此時(shí)服務(wù)器1票數(shù)一票,不夠半數(shù)以上(3票),選舉無法完成,服務(wù)器1狀態(tài)保持為LOOKING;
(2)服務(wù)器2啟動(dòng),再發(fā)起一次選舉。服務(wù)器1和2分別投自己一票并交換選票信息:此時(shí)服務(wù)器1發(fā)現(xiàn)服務(wù)器2的ID比自己目前投票推舉的(服務(wù)器1)大,更改選票為推舉服務(wù)器2。此時(shí)服務(wù)器1票數(shù)0票,服務(wù)器2票數(shù)2票,沒有半數(shù)以上結(jié)果,選舉無法完成,服務(wù)器1,2狀態(tài)保持LOOKING
(3)服務(wù)器3啟動(dòng),發(fā)起一次選舉。此時(shí)服務(wù)器1和2都會(huì)更改選票為服務(wù)器3。此次投票結(jié)果:服務(wù)器1為0票,服務(wù)器2為0票,服務(wù)器3為3票。此時(shí)服務(wù)器3的票數(shù)已經(jīng)超過半數(shù),服務(wù)器3當(dāng)選Leader。服務(wù)器1,2更改狀態(tài)為FOLLOWING,服務(wù)器3更改狀態(tài)為LEADING;
(4)服務(wù)器4啟動(dòng),發(fā)起一次選舉。此時(shí)服務(wù)器1,2,3已經(jīng)不是LOOKING狀態(tài),不會(huì)更改選票信息。交換選票信息結(jié)果:服務(wù)器3為3票,服務(wù)器4為1票。此時(shí)服務(wù)器4服從多數(shù),更改選票信息為服務(wù)器3,并更改狀態(tài)為FOLLOWING;
(5)服務(wù)器5啟動(dòng),同4一樣當(dāng)小弟。

6??寫數(shù)據(jù)流程

五 常見問題匯總

1?? ZooKeeper的部署方式有哪幾種?集群中的角色有哪些?集群最少需要幾臺(tái)機(jī)器?
(1)部署方式單機(jī)模式、集群模式
(2)角色:LeaderFollower
(3)集群最少需要機(jī)器數(shù):3

2??ZooKeeper的常用命令 : ls create get delete set…

3??ZooKeeper的選舉機(jī)制 : 參考4.5

4??ZooKeeper的監(jiān)聽原理是什么 : 參考4.3

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容