配置
1、在conf目錄下創建一個配置文件zoo.cfg
tickTime=2000
dataDir=.../zookeeper/data
dataLogDir=.../zookeeper/dataLog
clientPort=2181
initLimit=5
syncLimit=2
server.1=server1:2888:3888
server.2=server2:2888:3888
server.3=server3:2888:3888
?tickTime:發送心跳的間隔時間,單位:毫秒
?dataDir:zookeeper保存數據的目錄。
?clientPort:客戶端連接 Zookeeper 服務器的端口,Zookeeper 會監聽這個端口,接受客戶端的訪問請求。
?initLimit: 這個配置項是用來配置 Zookeeper 的Leader接受Follower 服務器初始化連接時最長能忍受多少個心跳時間間隔數。當已經超過 5 個心跳的時間(也就是 tickTime)長度后 Leader還沒有收到Follower的返回信息,那么表明這個Follower連接失敗。總的時間長度就是 5*2000=10 秒
?syncLimit:這個配置項標識 Leader 與 Follower 之間發送消息,請求和應答時間長度,最長不能超過多少個 tickTime 的時間長度,總的時間長度就是 2*2000=4 秒
?server.A=B:C:D:其 中 A 是一個數字,表示這個是第幾號服務器;B 是這個服務器的 ip地址;C 表示的是這個服務器與集群中的 Leader 服務器交換信息的端口;D 表示的是萬一集群中的 Leader 服務器掛了,需要一個端口來重新進行選舉,選出一個新的 Leader,而這個端口就是用來執行選舉時服務器相互通信的端口。如果是偽集群的配置方式,由于 B 都是一樣,所以不同的 Zookeeper 實例通信端口號不能一樣,所以要給它們分配不同的端口號。
2、在dataLogDir下創建myid文件。
server1機器的內容為1,server2機器的內容為2,server3的內容為3
常用命令:
zkServer.sh start
zkServer.sh status
zkCli.sh
zk命令行中:
ls
create path data ? ?如create /welcome hello,world
get path ? ? 如get /welcome
set path data ? ?如set /welcome hi
ZooKeeper的角色
領導者(leader),負責進行投票的發起和決議,更新系統狀態
學習者(learner),包括跟隨者(follower)和觀察者(observer)
follower用于接受客戶端請求并向客戶端返回結果,在選主過程中參與投票
observer可以接受客戶端連接,將寫請求轉發給leader,但observer不參加投票過程,只同步leader的狀態observer的目的是為了擴展系統,提高讀取速度
客戶端(client),請求發起方
Zookeeper的核心是原子廣播,這個機制保證了各個Server之間的同步。實現這個機制的協議叫做Zab協議。
Zab協議有兩種模式,它們分別是恢復模式(選主)和廣播模式(同步)。
當服務啟動或者在領導者崩潰后,Zab就進入了恢復模式,當領導者被選舉出來,且大多數Server完成了和leader的狀態同步以后,恢復模式就結束了。狀態同步保證了leader和Server具有相同的系統狀態。
為了保證事務的順序一致性,zookeeper采用了遞增的事務id號(zxid)來標識事務。所有的提議(proposal)都在被提出的時候加上了zxid。實現中zxid是一個64位的數字,它高32位是epoch用來標識leader關系是否改變,每次一個leader被選出來,它都會有一個新的epoch,標識當前屬于那個leader的統治時期。低32位用于遞增計數。
每個Server在工作過程中有三種狀態:
?LOOKING:當前Server不知道leader是誰,正在搜尋
?LEADING:當前Server即為選舉出來的leader
?FOLLOWING:leader已經選舉出來,當前Server與之同步
ZooKeeper的讀寫機制
? Zookeeper是一個由多個server組成的集群
? 一個leader,多個follower
? 每個server保存一份數據副本
? 全局數據一致
? 分布式讀寫
? 更新請求轉發,由leader實施
? 更新請求順序進行,來自同一個client的更新請求按其發送順序依次執行
? 數據更新原子性,一次數據更新要么成功,要么失敗
? 全局唯一數據視圖,client無論連接到哪個server,數據視圖都是一致的
? 實時性,在一定時間范圍內,client能讀到最新數據
Follower主要有四個功能:
1. 向Leader發送請求(PING消息、REQUEST消息、ACK消息、REVALIDATE消息);2 .接收Leader消息并進行處理;
3 .接收Client的請求,如果為寫請求,發送給Leader進行投票;
4 .返回Client結果。
Follower的消息循環處理如下幾種來自Leader的消息:
1 .PING消息: 心跳消息;
2 .PROPOSAL消息:Leader發起的提案,要求Follower投票;
3 .COMMIT消息:服務器端最新一次提案的信息;
4 .UPTODATE消息:表明同步完成;
5 .REVALIDATE消息:根據Leader的REVALIDATE結果,關閉待revalidate的session還是允許其接受消息;
6 .SYNC消息:返回SYNC結果到客戶端,這個消息最初由客戶端發起,用來強制得到最新的更新。
Leader選舉
奇數n的容錯性與偶數n+1的容錯性相同,所以沒有必要用偶數。
?A提案說,我要選自己,B你同意嗎?C你同意嗎?B說,我同意選A;C說,我同意選A。(注意,這里超過半數了,其實在現實世界選舉已經成功了。但是計算機世界是很嚴格,另外要理解算法,要繼續模擬下去。)
?接著B提案說,我要選自己,A你同意嗎;A說,我已經超半數同意當選,你的提案無效;C說,A已經超半數同意當選,B提案無效。
?接著C提案說,我要選自己,A你同意嗎;A說,我已經超半數同意當選,你的提案無效;B說,A已經超半數同意當選,C的提案無效。
?選舉已經產生了Leader,后面的都是follower,只能服從Leader的命令。
小細節,就是誰先啟動誰當Leader。
?zxid
? znode節點的狀態信息中包含czxid, 那么什么是zxid呢?? ZooKeeper狀態的每一次改變, 都對應著一個遞增的Transaction id, 該id稱為zxid. 由于zxid的遞增性質, 如果zxid1小于zxid2, 那么zxid1肯定先于zxid2發生. 創建任意節點, 或者更新任意節點的數據, 或者刪除任意節點, 都會導致
Zookeeper狀態發生改變, 從而導致zxid的值增加.
Zookeeper的核心是原子廣播,這個機制保證了各個server之間的同步。
實現這個機制的協議叫做Zab協議。
Zab協議有兩種模式,它們分別是恢復模式和廣播模式。
當服務啟動或者在領導者崩潰后,Zab就進入了恢復模式,當領導者被選舉出來,且大多數server的完成了和leader的狀態同步以后,恢復模式就結束了。狀態同步保證了leader和server具有相同的系統狀態。
一旦leader已經和多數的follower進行了狀態同步后,他就可以開始廣播消息了,即進入廣播狀態。
這時候當一個server加入zookeeper服務中,它會在恢復模式下啟動,發現leader,并和leader進行狀態同步。
待到同步結束,它也參與消息廣播。
Zookeeper服務一直維持在Broadcast狀態,直到leader崩潰了或者leader失去了大部分的followers支持。
廣播模式需要保證proposal被按順序處理,因此zk采用了遞增的事務id號(zxid)來保證。
所有的提議(proposal)都在被提出的時候加上了zxid。
實現中zxid是一個64為的數字,它高32位是epoch用來標識leader關系是否改變,每次一個leader被選出來,它
都會有一個新的epoch。低32位是個遞增計數。
當leader崩潰或者leader失去大多數的follower,這時候zk進入恢復模式,恢復模式需要重新選舉出一個新的leader,讓所有的server都恢復到一個正確的狀態。
Leader選舉:
? 每個Server啟動以后都詢問其它的Server它要投票給誰。
? 對于其他server的詢問,server每次根據自己的狀態都回復自己推薦的leader的id和上一次處理事務的zxid(系統啟動時每個server都會推薦自己)
? 收到所有Server回復以后,就計算出zxid最大的哪個Server,并將這個Server相關信息設置成下一次要投票的Server。
? 計算這過程中獲得票數最多的的sever為獲勝者,如果獲勝者的票數超過半數,則改server被選為leader。否則,繼續這個過程,直到leader被選舉出來。
? leader就會開始等待server連接
? Follower連接leader,將最大的zxid發送給leader
? Leader根據follower的zxid確定同步點
? 完成同步后通知follower 已經成為uptodate狀態
? Follower收到uptodate消息后,又可以重新接受client的請求進行服務了
Observer ?
? Zookeeper需保證高可用和強一致性;
? 為了支持更多的客戶端,需要增加更多Server;
? Server增多,投票階段延遲增大,影響性能;
? 權衡伸縮性和高吞吐率,引入Observer ?
? Observer不參與投票;
? Observers接受客戶端的連接,并將寫請求轉發給leader節點;
? 加入更多Observer節點,提高伸縮性,同時不影響吞吐率
?為什么zookeeper集群的數目,一般為奇數個?
Leader選舉算法采用了Paxos協議;Paxos核心思想:當多數Server寫成功,則任務數據寫成功。如果有3個Server,則兩個寫成功即可;
如果有4或5個Server,則三個寫成功即可。
Server數目一般為奇數(3、5、7)
如果有3個Server,則最多允許1個Server掛掉;
如果有4個Server,則同樣最多允許1個Server掛掉;
由此,我們看出3臺服務器和4臺服務器的的容災能力是一樣的,所以為了節省服務器資源,一般我們采用奇數個數,作為服務器部署個數。