摘要:節點增刪所有機器約定在父目錄下創建臨時目錄節點,然后監聽父目錄節點的子節點變化消息。鎖服務分為保存獨占及時序控制兩類。跟隨者用于接收客戶請求并向客戶端返回結果,在選中過程中參與投票。但不參加投票過程只同步狀態。
zookeeper zookeeper是什么
Apache ZooKeeper是Apache軟件基金會的一個軟件項目,他為大型分布式計算提供開源的分布式配置服務、同步服務和命名注冊。ZooKeeper曾經是Hadoop的一個子項目,但現在是一個獨立的頂級項目。
ZooKeeper的架構通過冗余服務實現高可用性。因此,如果第一次無應答,客戶端就可以詢問另一臺ZooKeeper主機。ZooKeeper節點將它們的數據存儲于一個分層的命名空間,非常類似于一個文件系統或一個前綴樹結構。客戶端可以在節點讀寫,從而以這種方式擁有一個共享的配置服務。
使用ZooKeeper的公司包括Rackspace、雅虎和eBay,以及類似于像Solr這樣的開源企業級搜索系統。
zookeeper提供了什么
文件系統:zookeeper維護一個類似文件系統的數據結構,每個子目錄項如 NameService 都被稱作為 znode,和文件系統一樣,自由增加及刪除,唯一不同其可存儲數據。Znode分為四種類型
PERSISTENT-持久化目錄節點。(客戶端與zookeeper斷開連接后,該節點依舊存在)。
PERSISTENT_SEQUENTIAL-持久化順序編號目錄節點。(客戶端與zookeeper斷開連接后,該節點依舊存在,只是Zookeeper給該節點名稱進行順序編號)
EPHEMERAL-臨時目錄節點(客戶端與zookeeper斷開連接后,該節點被刪除)
EPHEMERAL_SEQUENTIAL-臨時順序編號目錄節點。(客戶端與zookeeper斷開連接后,該節點被刪除,只是Zookeeper給該節點名稱進行順序編號)
通知機制:客戶端注冊監聽它關心的目錄節點,當目錄節點發生變化(數據改變、被刪除、子目錄節點增加刪除)時,zookeeper會通知客戶端。
zookeeper能為我們做什么?命名服務:在zookeeper的文件系統里創建一個目錄,即有唯一的path。在我們使用tborg無法確定上游程序的部署機器時即可與下游程序約定好path,通過path即能互相探索發現。
配置管理:把應用配置放置zookeeper上去,保存在 Zookeeper 的某個目錄節點中,然后所有相關應用程序對這個目錄節點進行監聽,一旦配置信息發生變化,每個應用程序就會收到 Zookeeper 的通知,然后從 Zookeeper 獲取新的配置信息應用到系統中就好。
集群管理:節點(機器)增刪及Master選取。節點增刪:所有機器約定在父目錄GroupMembers下創建臨時目錄節點,然后監聽父目錄節點的子節點變化消息。一旦有機器掛掉,該機器與 zookeeper的連接斷開,其所創建的臨時目錄節點被刪除,所有其他機器都收到通知:某個兄弟目錄被刪除,于是,所有人都知道:它上船了。新機器加入 也是類似,所有機器收到通知:新兄弟目錄加入,highcount又有了。Master選取:所有機器創建臨時順序編號目錄節點,每次選取編號最小的機器作為master就好。
分布式鎖:基于zookeeper一致性文件系統,實現鎖服務。鎖服務分為保存獨占及時序控制兩類。保存獨占:將zookeeper上的一個znode看作是一把鎖,通過createznode的方式來實現。所有客戶端都去創建 /distribute_lock 節點,最終成功創建的那個客戶端也即擁有了這把鎖。用完刪除自己創建的distribute_lock 節點就釋放鎖。時序控制:基于/distribute_lock鎖,所有客戶端在它下面創建臨時順序編號目錄節點,和選master一樣,編號最小的獲得鎖,用完刪除,依次方便。
隊列管理:分同步隊列,FIFO隊列(入隊與出隊),同步隊列:當一個隊列的成員都聚齊時,這個隊列才可用,否則一直等待所有成員到達。在約定目錄下創建臨時目錄節點,監聽節點數目是否是我們要求的數目。FIFO隊列:和分布式鎖服務中的控制時序場景基本原理一致,入列有編號,出列按編號。
分布式與數據復制:Zookeeper作為一個集群提供一致的數據服務,必然在所有機器間做數據復制。數據復制好處:(1)容錯:一個節點出錯,不致于讓整個系統停止工作,別的節點可以接管它的工作。(2)提高系統的擴展能力:把負載分布到多個節點上,或者增加節點來提高系統的負載能力;(3)性能提升:讓客戶端本地訪問就近節點,提高用戶訪問速度。
zookeeper基本概念 角色簡介Zookeeper角色分為三類,領導者:負責進行投票的發起和決議,更新系統狀態。跟隨者:Follower用于接收客戶請求并向客戶端返回結果,在選中過程中參與投票。觀察者:Observer可以接收客戶端連接,將寫請求轉發給leader節點。但不參加投票過程,只同步leader狀態。Observer目的在于擴展系統,提高讀取速度。
設計目的一致性:client不論連接到哪個Server,展示給它都是同一個視圖,這是zookeeper最重要的性能。
可靠性:具有簡單、健壯、良好的性能,如果消息m被到一臺服務器接受,那么它將被所有的服務器接受。
實時性:Zookeeper保證客戶端將在一個時間間隔范圍內獲得服務器的更新信息,或者服務器失效的信息。但由于網絡延時等原因,Zookeeper不能保證兩個客戶端能同時得到剛更新的數據,如果需要最新數據,應該在讀數據之前調用sync()接口。
等待無關(wait-free):慢的或者失效的client不得干預快速的client的請求,使得每個client都能有效的等待。
原子性:更新只能成功或者失敗,沒有中間狀態。
順序性:包括全局有序和偏序兩種:全局有序是指如果在一臺服務器上消息a在消息b前發布,則在所有Server上消息a都將在消息b前被發布;偏序是指如果一個消息b在消息a后被同一個發送者發布,a必將排在b前面。
選主流程當leader崩潰或者leader失去大多數的follower,這時候zk進入恢復模式,恢復模式需要重新選舉出一個新的leader,讓所有的Server都恢復到一個正確的狀態。Zk的選舉算法有兩種:一種是基于basic paxos實現的,另外一種是基于fast paxos算法實現的。系統默認的選舉算法為fast paxos。先介紹basic paxos流程:
選舉線程由當前Server發起選舉的線程擔任,其主要功能是對投票結果進行統計,并選出推薦的Server;
選舉線程首先向所有Server發起一次詢問(包括自己);
選舉線程收到回復后,驗證是否是自己發起的詢問(驗證zxid是否一致),然后獲取對方的id(myid),并存儲到當前詢問對象列表中,最后獲取對方提議的leader相關信息(id,zxid),并將這些信息存儲到當次選舉的投票記錄表中;
收到所有Server回復以后,就計算出zxid最大的那個Server,并將這個Server相關信息設置成下一次要投票的Server;
線程將當前zxid最大的Server設置為當前Server要推薦的Leader,如果此時獲勝的Server獲得n/2 + 1的Server票數, 設置當前推薦的leader為獲勝的Server,將根據獲勝的Server相關信息設置自己的狀態,否則,繼續這個過程,直到leader被選舉出來。
通過流程分析我們可以得出:要使Leader獲得多數Server的支持,則Server總數必須是奇數2n+1,且存活的Server的數目不得少于n+1.
每個Server啟動后都會重復以上流程。在恢復模式下,如果是剛從崩潰狀態恢復的或者剛啟動的server還會從磁盤快照中恢復數據和會話信息,zk會記錄事務日志并定期進行快照,方便在恢復時進行狀態恢復。
fast paxos流程是在選舉過程中,某Server首先向所有Server提議自己要成為leader,當其它Server收到提議以后,解決epoch和zxid的沖突,并接受對方的提議,然后向對方發送接受提議完成的消息,重復這個流程,最后一定能選舉出Leader。
zookeeper的安裝使用wget http://mirrors.cnnic.cn/apache/zookeeper/zookeeper-3.4.8/zookeeper-3.4.8.tar.gz tar zxvf zookeeper-3.4.8.tar.gz -C /usr/local/ cd $ZOOKEEPER_HOME cp conf/zoo_sample.cfg conf/zoo.cfg # 集群需要在zoo.cfg配置 server.1=192.168.1.148:2888:3888 server.2=192.168.1.149:2888:3888 server.3=192.168.1.150:2888:3888 # 在zookeeper的臨時目錄創建myid mkdir -p /tmp/zookeeper # 分別在不同節點創建myid文件里面的數字對應節點的編號比如server.1就對應1,server.2就對應2 echo 1 > /tmp/zookeeper/myid # 最后分別啟動集群上的節點 $ZOOKEEPER_HOME/bin/zkServer.sh start # 查看zookeeper的狀態 $ZOOKEEPER_HOME/bin/zkServer.sh status # 停止zookeeper服務 $ZOOKEEPER_HOME/bin/zkServer.sh stopzookeeper命令行操作
啟動zookeeper服務后到bin目錄啟動zookeeper的客戶端$ZOOKEEPER_HOME/bin/zkCli.sh
# 輸入help [zk: localhost:2181(CONNECTED) 0] help ZooKeeper -server host:port cmd args stat path [watch] set path data [version] ls path [watch] delquota [-n|-b] path ls2 path [watch] setAcl path acl setquota -n|-b val path history redo cmdno printwatches on|off delete path [version] sync path listquota path rmr path get path [watch] create [-s] [-e] path data acl addauth scheme auth quit getAcl path close connect host:port
創建節點
[zk: localhost:2181(CONNECTED) 14] create /test test-data Created /test
查看節點
[zk: localhost:2181(CONNECTED) 1] ls / [abc, zookeeper, eclipse]
獲取節點
[zk: localhost:2181(CONNECTED) 10] get /test test-update cZxid = 0x38 ctime = Sat Dec 22 10:11:46 CST 2018 mZxid = 0x39 mtime = Sat Dec 22 10:12:05 CST 2018 pZxid = 0x38 cversion = 0 dataVersion = 1 aclVersion = 0 ephemeralOwner = 0x0 dataLength = 11 numChildren = 0
修改節點
[zk: localhost:2181(CONNECTED) 11] set /test test-update cZxid = 0x38 ctime = Sat Dec 22 10:11:46 CST 2018 mZxid = 0x3a mtime = Sat Dec 22 10:15:04 CST 2018 pZxid = 0x38 cversion = 0 dataVersion = 2 aclVersion = 0 ephemeralOwner = 0x0 dataLength = 11 numChildren = 0
刪除節點
[zk: localhost:2181(CONNECTED) 13] delete /testzookeeper java 客戶端操作
/** * @author leone * @since 2018-06-16 **/ public class ZkClient { private final static Logger logger = LoggerFactory.getLogger(ZkClient.class); private final static String ZK_URL = "xxx.xxx.xxx.xxx:2181"; private final static int TIME_OUT = 5000; private static ZooKeeper zkClient = null; @Before public void init() throws Exception { zkClient = new ZooKeeper(ZK_URL, TIME_OUT, (WatchedEvent event) -> { // 收到事件通知后的回調函數(應該是我們自己的事件處理邏輯) logger.info(event.getType() + "---" + event.getPath()); try { zkClient.getChildren("/", true); } catch (Exception e) { e.printStackTrace(); } }); } /** * 設置值 * * @throws Exception */ @Test public void testSetData() throws Exception { zkClient.setData("/eclipse", "world".getBytes(), -1); byte[] data = zkClient.getData("/eclipse", false, null); System.out.println(new String(data)); } /** * 創建節點 * * @throws Exception */ @Test public void testCreate() throws Exception { // 參數1:要創建的節點的路徑 參數2:節點數據 參數3:節點的權限 參數4:節點的類型 zkClient.create("/eclipse/aaa", "aaaData".getBytes(), ZooDefs.Ids.OPEN_ACL_UNSAFE, CreateMode.PERSISTENT); } /** * 測試某節點是否存在 * * @throws Exception */ @Test public void testExists() throws Exception { Stat stat = zkClient.exists("/eclipse", false); System.out.println(stat == null ? "not exist" : "exist"); } /** * 獲取子節點 * * @throws Exception */ @Test public void testGetChild() throws Exception { Listchildren = zkClient.getChildren("/", true); for (String child : children) { System.out.println(child); } } /** * 刪除節點 * * @throws Exception */ @Test public void testDelete() throws Exception { // 參數2:指定要刪除的版本,-1表示刪除所有版本 zkClient.delete("/abc", -1); } /** * 獲取節點的數據 * * @throws Exception */ @Test public void testGetDate() throws Exception { byte[] data = zkClient.getData("/eclipse", false, null); System.out.println(new String(data)); } }
文章版權歸作者所有,未經允許請勿轉載,若此文章存在違規行為,您可以聯系管理員刪除。
轉載請注明本文地址:http://specialneedsforspecialkids.com/yun/74320.html
摘要:附帶的這些示例配置文件使用您之前啟動的默認本地群集配置,并創建兩個連接器第一個是源連接器,用于讀取輸入文件中的行,并將每個連接生成為,第二個為連接器它從讀取消息,并在輸出文件中產生每行消息。 轉載請注明原創地址為:http://www.54tianzhisheng.cn/2018/01/04/Kafka/ showImg(https://segmentfault.com/img/rem...
摘要:附帶的這些示例配置文件使用您之前啟動的默認本地群集配置,并創建兩個連接器第一個是源連接器,用于讀取輸入文件中的行,并將每個連接生成為,第二個為連接器它從讀取消息,并在輸出文件中產生每行消息。 轉載請注明原創地址為:http://www.54tianzhisheng.cn/2018/01/04/Kafka/ showImg(http://ohfk1r827.bkt.clouddn.com...
閱讀 2265·2023-04-25 23:15
閱讀 1917·2021-11-22 09:34
閱讀 1546·2021-11-15 11:39
閱讀 955·2021-11-15 11:37
閱讀 2152·2021-10-14 09:43
閱讀 3493·2021-09-27 13:59
閱讀 1506·2019-08-30 15:43
閱讀 3454·2019-08-30 15:43