一 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 =10:LF初始通信時(shí)限集群中的Follower跟隨者服務(wù)器與Leader領(lǐng)導(dǎo)者服務(wù)器之間初始連接時(shí)能容忍的最多心跳數(shù)(tickTime的數(shù)量),用它來限定集群中的Zookeeper服務(wù)器連接到Leader的時(shí)限。
?3.syncLimit =5:LF同步通信時(shí)限集群中Leader與Follower之間的最大響應(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ī)劃 : 在hadoop102、hadoop103和hadoop104三個(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.cfg為zoo.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)分別啟動(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:/sanguo11.節(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:/sanguo12.刪除節(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
- 創(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(); } } });
- 創(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); }
- 獲取子節(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); }
- 判斷
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ù)ID是ZooKeeper中所有修改總的次序。每個(gè)修改都有唯一的zxid,如果zxid1小于zxid2,那么zxid1在zxid2之前發(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è)提案的Value和Proposal ID,沒有則返回空值。
3.Propose:Proposer收到多數(shù)Acceptors的Promise應(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ù)Acceptors的Accept后,決議形成,將形成的決議發(fā)送給所有Learners。
下面我們針對上述描述做三種情況的推演舉例:為了簡化流程,我們這里不設(shè)置Learner。情況1??情況2Paxos算法缺陷:在網(wǎng)絡(luò)復(fù)雜的情況下,一個(gè)應(yīng)用Paxos算法的分布式系統(tǒng),可能很久無法收斂,甚至陷入活鎖的情況。??造成這種情況的原因是系統(tǒng)中有一個(gè)以上的情況3Proposer,多個(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雖然在配置文件中并沒有指定Master和Slave。但是,Zookeeper工作時(shí),是有一個(gè)節(jié)點(diǎn)為Leader,其他則為Follower,Leader是通過內(nèi)部的選舉機(jī)制臨時(shí)產(chǎn)生的。
3)以一個(gè)簡單的例子來說明整個(gè)選舉的過程。
??假設(shè)有五臺(tái)服務(wù)器組成的Zookeeper集群,它們的id從1-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)角色:Leader和Follower
(3)集群最少需要機(jī)器數(shù):3
2??
ZooKeeper的常用命令 :ls create get delete set…
3??
ZooKeeper的選舉機(jī)制 : 參考4.5
4??
ZooKeeper的監(jiān)聽原理是什么 : 參考4.3

















