zookeeper是大數據hadoop生態圈中的一個框架,是一種用於分佈式應用程序的高性能協調服務。註冊中心是zookeeper的別名。java
zookeeper是一個致力於開發和維護的開源服務器,做用於項目中的協調和控制功能。程序員
zookeeper最先是hadoop生態圈中的一員,hadoop生態圈的框架都是動物,而zookeeper就是管理這些動物的,字面意思就是動物管理員,它負責監聽各個框架的健康情況,服務器的調用方和生產方。在以往的項目中都是經過直接客戶端直接訪問服務器來進行交互式訪問,而使用zookeeper後,客戶端的請求發送到zookeeper,而後根據zookeeper的反饋再找服務器端。web
zookeeper中存放了大量的數據,服務器端再zookeeper中註冊服務,而後zookeeper就會按期向這些註冊過的服務索要心跳,根據觀察者模式,一旦檢測到狀態發生變化,就要向zookeeper註冊過的服務器(觀察者)應對處理的措施。算法
觀察者模式:apache
觀察者模式是一種設計模式,當對象間存在一對多關係時,則使用觀察者模式(Observer Pattern)。好比,當一個對象被修改時,則會自動通知它的依賴對象。觀察者模式屬於行爲型模式。再zookeeper中,zookeeper是被觀察者,再zookeeper中註冊的服務都是觀察者。設計模式
zookeeper在以前只適用於hadoop,可是隨着web項目愈來愈大,發展愈來愈快,zookeeper已經徹底適應了web項目,在web項目中仍然起着協調和控制的做用。服務器
zookeeper是以集羣的形式存在,也就是三臺服務器作同一件事,官方文檔說明,zookeeper以奇數臺爲穩定,而且中間的一臺爲leader,也就是說至少須要三臺(一臺稱之爲單節點,不能稱爲集羣)app
爲何說奇數臺最穩定?框架
與zookeeper的選舉機制有關,zookeeper集羣會選舉一臺服務器爲leader,其餘的都是follower,也就是一個領導者帶領一羣小弟作一件事。ssh
1.官網下載zookeeper.tar.gz壓縮包
2.新建三臺虛擬機,並修改HOSTNAME,hosts,關閉防火牆,防火牆開機自啓動,重啓虛擬機
3.zookeeper集羣之間要可以通訊,所以須要配置免密鑰登陸(免密鑰登陸在前面有介紹: ssh-keygen -t rsa ssh-copy-id ip地址 )
4.下載jdk.tar.gz(由於zookeepre是apache公司的,apache的項目於必須運行在jdk環境中,所以須要配置jdk)
5.配置完免密鑰登陸後,測試是否各服務器之間是否聯通,而後將jdk解壓,並安裝jdk,配置環境變量,測試環境變量是否配置成功(javac)
6.解壓zookeeper壓縮包,修改conf文件夾下的zoo_simple.cfg文件名稱爲zoo.cfg: mv zoo_simple.cfg zoo.cfg
7.在zookeeper的主目錄中建立data文件夾
7.修改zoo.cfg文件,將 dataDir後的路徑修改成剛建立的data文件夾的路徑,並在末尾添加
server.1=zookeeper01:2888:3888 server.2=zookeeper02:2888:3888 server.3=zookeeper03:2888:3888
server.1:表示zookeeper集羣中服務器的id,id是服務器的惟一標識,
zookeeper01:是服務器修改的HOSTNAME,也能夠是IP地址
2888:是集羣之間通信所用的端口號
3888:是選舉leader使用的端口號
8.在data文件夾下建立myid文件 touch myid ,並編輯文件,文件中存的是當前zookeeer的id,文件中只輸入1保存退出。
在上一步中,server.1 1就是一個zookeeper服務器的id,這一步就是代表id爲1的服務器是哪兒一臺,myid中存放的就是本臺服務器的id 1
9.使用scp命令將第一臺服務器上的jdk以及環境變量配置文件/etc/profile,以及zookeeper文件傳輸到其餘的服務器:
scp -r /home/apps zookeeper02:/home/ (個人jdk以及zookeeper文件都在apps文件夾下,所以直接傳文件夾過去)
scp -r /etc/profile zookeeper02:/etc/ 傳遞配置文件,也能夠手動一個一個配,都須要從新加載文件 source /etc/profile
10.進入其餘的服務器,測試jdk是否配置成功:javac
11.進入zookeeper目錄下的bin目錄,分別啓動三臺zookeeper cd /home/apps/zookeeperxxx/bin ./zkServer.sh start
表示啓動成功
12.查看當前zookeeper的狀態, ./zkServer.sh status
zookeeper集羣啓動成功後, 經過查看狀態能夠看到有一臺爲leader,其餘的都爲follower,並且leader爲中間的一臺。
zookeeper採用的是Paxos算法實現的選舉機制,換句話說是半數選舉機制
zookeeper在選舉leader的時候是處於癱瘓狀態的,若是當前zookeeper集羣的leader宕機了,那麼,就會從新選舉leader,此次選舉使用的並不在是半數選舉,會經過zxid來選舉leader,zxid是事務的id,有64位,高32位是同樣的,低32位越小,被操做的可能性就越高。
假設如今啓動三臺zookeeper,而後中間的2號機爲leader,若是2號忽然宕機,那麼根據半數選舉的話,應該是3號成爲leader的可能新大,可是實際上leader倒是1號。
數據一致性(集羣上的每個節點上的數據都要保持一致)
當服務消費者去zookeeper中查詢服務生產者的時候,只會從leader服務器中查詢數據;
當服務生產者到zookeeper中註冊本身的時候,一樣只會在leader中註冊本身,那麼就會有一個問題,只有leader中有數據,若是leader宕機,那麼全部的數據都會丟失?
解決辦法:leader會按期的將本身的數據(元數據)發送給follower(這種行爲成爲數據的同步);
leader會按期接受follower的心跳,follower也會按期向leader發送心跳。
若是follower1向leader中發送心跳,可是沒有發送成功,這時follower1並不能肯定leader是否已經宕機(單一的節點不能肯定leader是否宕機,當全部的follower都沒法發送心跳時,才能夠肯定宕機,須要經過選舉機制從新選舉)。
若是隻有follower1發送心跳失敗,可是follower3發送數據成功---->這時,leader就會默認等待30秒,若是30秒後,仍是沒有接收到follower1的心跳,就會宣佈follower1宕機---->生成日誌信息,通知程序員follower1宕機----->程序員搶修follower1,而後重啓follower1----->leader將本身的數據同步給follower1。
問題:當leader宕機後,服務生產者是否還能在zookeeper中註冊本身?
(leader宕機後,follower會從新選舉leader(官方給的時間30~120s),選舉leader過程當中,zookeeper處於癱瘓狀態)
能夠繼續註冊,當leader宕機後,在從新選舉期間,若是有服務註冊進來,全部的服務都註冊在leader上,可是leader宕機,這時尚未leader,那麼zookeeper就會讓服務註冊在zxid低32位較小的那個節點上(由於低32位越小,成爲leader的可能性就越高),這樣選舉結束後,發現註冊服務的節點並無成爲leader,那麼就同步數據給其餘的follower,若是沒有成爲leader,就將本身的數據共享給leader。
問題:當leader宕機後,若是服務消費者到zookeeper中查詢數據時,是否能查詢到數據?
能夠查詢到,可是zookeeper由於機制問題,會讓服務消費者一直處於等待狀態,等待leader選舉完成
服務消費者進到zookeeper後會到leader中獲取數據,可是這時leader宕機,沒有leader,這是zookeeper就會拉住不讓消費者走,它會讓zxid低32位小的那個節點來接待消費者(由於該節點成爲leader的可能性大),消費者會從這個節點中獲取數據,服務註冊時,也是註冊在這個節點上,所以獲取到的數據是比較新的數據,可是獲取到數據後,並不讓消費者走,而是要等待leader選舉成功後,纔會放消費者走(leader選舉成功後,這時的消費者已經獲取到數據了),這就會形成髒數據,這是zookeeper的缺陷。
問題:zookeeper機制的缺陷
接着上面的問題解決思路,若是在leader選舉的過程當中,消費者到leader中查詢數據了,查詢的同時,有不少的服務註冊了進來,那麼此時消費者獲取到的是新的數據,當leader選舉成功後,消費者看到的是新的數據,這時消費者刷新頁面,再次到zookeeper中獲取數據,這時已經有了leader,可是follower中的數據共享到leader也是須要時間的,假設此時follower中的數據尚未徹底共享到leader中,這時消費者到eader中查詢到的數據就是舊的數據(髒數據),消費者再次刷新,再次查詢數據時,數據共享已經完成,leader返回的是新數據,這樣就會出現 新數據----->舊數據-------->新數據,這是zookeeper所面臨的問題。