ZooKeeper介紹:
ZooKeeper是一個(gè)分布式協(xié)調(diào)服務(wù),用于服務(wù)治理.
提供了文件系統(tǒng),通知機(jī)制,分布式應(yīng)用程序可以基于Zookeeper實(shí)現(xiàn)諸如數(shù)據(jù)發(fā)布/訂閱、負(fù)載均衡、命名服務(wù)渔隶、分布式協(xié)調(diào)/通知鳞溉、集群管理牛柒、Master選舉、分布式鎖和分布式隊(duì)列等功能磨总。為分布式系統(tǒng)解決數(shù)據(jù)同步問(wèn)題,任務(wù)執(zhí)行順序問(wèn)題,master選舉問(wèn)題,事務(wù)一致性問(wèn)題。
ZooKeeper的設(shè)計(jì)思想:
防止單點(diǎn)故障:采用高可用和高性能(分?jǐn)偭髁?的集群方案冲呢。
要實(shí)現(xiàn)高可用必須保證每個(gè)節(jié)點(diǎn)數(shù)據(jù)的一致性:
要實(shí)現(xiàn)各個(gè)節(jié)點(diǎn)的數(shù)據(jù)一致性舍败,就勢(shì)必要一個(gè)leader節(jié)點(diǎn)負(fù)責(zé)協(xié)調(diào)和數(shù)據(jù)同步操作。
如何舉出 leader 節(jié)點(diǎn)敬拓,leader節(jié)點(diǎn)宕機(jī)如何恢復(fù)數(shù)據(jù):
采用ZAB協(xié)議
如何保證分布式事務(wù)一致性(ACID):
解決分布式事務(wù)的數(shù)據(jù)一致性協(xié)議有2PC協(xié)議和3PC協(xié)議邻薯。
ZooKeeper集群角色:
Leader角色:
負(fù)責(zé)協(xié)調(diào)和數(shù)據(jù)同步操作.
1.事務(wù)請(qǐng)求的唯一調(diào)度和處理者,保證集群事物處理的順序性
2.集群內(nèi)部各服務(wù)器的調(diào)度者
Follower角色:
1.處理客戶端非事物請(qǐng)求、轉(zhuǎn)發(fā)事物請(qǐng)求給leader服務(wù)器
2.參與事務(wù)請(qǐng)求提議(proposal)投票
3.參與leader投票
Observer角色:
類似Follower角色,處理客戶端非事物請(qǐng)求乘凸、轉(zhuǎn)發(fā)事物請(qǐng)求給leader服務(wù)器
單不參與任何形式投票
集群組成:
集群規(guī)則為2N+1臺(tái)厕诡,N>0,即3臺(tái)营勤。
zookeeper是如何保證事務(wù)的順序一致性的灵嫌?
當(dāng)處理事務(wù)請(qǐng)求時(shí),會(huì)先成一個(gè)事務(wù)ID(ZXID)如圖葛作,同一個(gè)Leader的統(tǒng)治下epoch(leader周期)是相同的寿羞,counter消息計(jì)數(shù)器隨著事務(wù)的增加而遞增,會(huì)按照請(qǐng)求順序轉(zhuǎn)發(fā)給Leader赂蠢,并保存在一個(gè)FIFO隊(duì)列中绪穆,這樣就可以保證事務(wù)的順序一致性。然后
1.事務(wù)請(qǐng)求發(fā)送到follower服務(wù)器節(jié)點(diǎn)(若發(fā)送給Leader節(jié)點(diǎn)少了轉(zhuǎn)發(fā)這一步)
2.首先會(huì)把事務(wù)請(qǐng)求轉(zhuǎn)發(fā)給leader,
3.leader 服務(wù)器把客戶端的失去請(qǐng)求轉(zhuǎn)化成一個(gè)事務(wù) Proposal(提議)玖院,并把這個(gè) Proposal 分發(fā)給集群中的所有 Follower 服務(wù)器菠红,
4.如果過(guò)半的follower節(jié)點(diǎn)同意(返回ACK)
5.Leader 就會(huì)再次向所有的Follower 服務(wù)器發(fā)送 Commit 消息,要求各個(gè) follower 節(jié)點(diǎn)對(duì)前面的一個(gè) Proposal 進(jìn)行提交;
6.把最后的結(jié)果同步給Observer節(jié)點(diǎn),
7.把結(jié)果返回給客戶端难菌。
ZAB協(xié)議试溯?
ZAB協(xié)議是為分布式協(xié)調(diào)服務(wù)Zookeeper專門設(shè)計(jì)的一種支持崩潰恢復(fù)的原子廣播協(xié)議。
ZAB協(xié)議包括兩種基本的模式:崩潰恢復(fù)和消息廣播郊酒。
消息廣播存在事務(wù)處理實(shí)現(xiàn)原理:
1. Leader 接收到消息請(qǐng)求后遇绞,將消息賦予一個(gè)全局唯一的64 位自增 id,叫:zxid燎窘,通過(guò) zxid 的大小比較實(shí)現(xiàn)順序特征试读;
2. Leader 為每個(gè) follower 準(zhǔn)備了一個(gè) FIFO 隊(duì)列(通過(guò) TCP協(xié)議來(lái)實(shí)現(xiàn),以實(shí)現(xiàn)了全局有序這一個(gè)特點(diǎn))將帶有 zxid的消息作為一個(gè)提案(proposal)分發(fā)給所有的 follower荠耽;
3.當(dāng) follower 接收到 proposal钩骇,先把 proposal 寫到磁盤,寫入成功以后再向 leader 回復(fù)一個(gè) ack
4.當(dāng) leader 接收到合法數(shù)量(超過(guò)半數(shù)節(jié)點(diǎn))的 ACK 后铝量,leader 就會(huì)向這些 follower 發(fā)送 commit 命令倘屹,同時(shí)會(huì)在本地執(zhí)行該消息
5.當(dāng) follower 收到消息的 commit 命令以后,會(huì)提交該消息
崩潰恢復(fù)(數(shù)據(jù)恢復(fù))原理:
由于Leader節(jié)點(diǎn)崩潰或者由于網(wǎng)絡(luò)問(wèn)題導(dǎo)致Leader 服務(wù)器失去了過(guò)半的 Follower 節(jié)點(diǎn)的聯(lián)系那么就會(huì)進(jìn)入到崩潰恢復(fù)模式慢叨。重新選取leader
已經(jīng)被處理的消息不能丟失
leader發(fā)送commit消息給follower-A但發(fā)送給follower-B的時(shí)候掛了纽匙。zab協(xié)議下需要保證所有機(jī)器都要執(zhí)行這個(gè)事務(wù)消息
被丟棄的消息不能再次出現(xiàn)
當(dāng)提議生成但未發(fā)送到follower時(shí)掛了,重新選舉后,原leader保留這個(gè)提議,與整個(gè)系統(tǒng)狀態(tài)不一樣需要?jiǎng)h除這個(gè)提議。
Leaderr選舉:
Leader 選舉會(huì)分兩個(gè)過(guò)程:
啟動(dòng)的時(shí)候的leader選舉
leader 崩潰的時(shí)候的的選舉
服務(wù)器啟動(dòng)時(shí)的 leader 選舉
每個(gè)節(jié)點(diǎn)啟動(dòng)的時(shí)候狀態(tài)都是 LOOKING拍谐,處于觀望狀態(tài)烛缔,接下來(lái)就開始進(jìn)行選主流程
進(jìn)行 Leader 選舉,至少需要兩臺(tái)機(jī)器(具體原因前面已經(jīng)講過(guò)了)轩拨,我們選取 3 臺(tái)機(jī)器組成的服務(wù)器集群為例践瓷。在集群初始化階段,當(dāng)有一臺(tái)服務(wù)器 Server1 啟動(dòng)時(shí)亡蓉,它本身是無(wú)法進(jìn)行和完成 Leader 選舉晕翠,當(dāng)?shù)诙_(tái)服務(wù)器 Server2 啟動(dòng)時(shí),這個(gè)時(shí)候兩臺(tái)機(jī)器可以相互通信砍濒,每臺(tái)機(jī)器都試圖找到 Leader淋肾,于是進(jìn)入 Leader 選舉過(guò)程。選舉過(guò)程如下:
(1) 每個(gè) Server 發(fā)出一個(gè)投票爸邢。由于是初始情況樊卓,Server1和 Server2 都會(huì)將自己作為 Leader 服務(wù)器來(lái)進(jìn)行投票,每次投票會(huì)包含所推舉的服務(wù)器的 myid 和 ZXID杠河、epoch碌尔,使用(myid, ZXID,epoch)來(lái)表示赶掖,此時(shí) Server1的投票為(1, 0),Server2 的投票為(2, 0)七扰,然后各自將這個(gè)投票發(fā)給集群中其他機(jī)器。
(2)接受來(lái)自各個(gè)服務(wù)器的投票陪白。集群的每個(gè)服務(wù)器收到投票后颈走,首先判斷該投票的有效性,如檢查是否是本輪投票(epoch)咱士、是否來(lái)自LOOKING狀態(tài)的服務(wù)器立由。
(3) 處理投票。針對(duì)每一個(gè)投票序厉,服務(wù)器都需要將別人的投票和自己的投票進(jìn)行 PK锐膜,PK 規(guī)則如下
i.優(yōu)先檢查 ZXID。ZXID 比較大的服務(wù)器優(yōu)先作為L(zhǎng)eader
如果 leader 選舉算法能夠保證新選舉出來(lái)的 Leader 服務(wù)器擁有集群中所有機(jī)器最高編號(hào)(ZXID 最大)的事務(wù)Proposal弛房,那么就可以保證這個(gè)新選舉出來(lái)的 Leader 一定具有已經(jīng)提交的提案道盏。因?yàn)樗刑岚副?COMMIT 之前必須有超過(guò)半數(shù)的 follower ACK,即必須有超過(guò)半數(shù)節(jié)點(diǎn)的服務(wù)器的事務(wù)日志上有該提案的 proposal文捶,因此荷逞,只要有合法數(shù)量的節(jié)點(diǎn)正常工作,就必然有一個(gè)節(jié)點(diǎn)保存了所有被 COMMIT 消息的 proposal 狀態(tài)
ii. 如果 ZXID 相同粹排,那么就比較 myid种远。myid 較大的服務(wù)器作為 Leader 服務(wù)器。
對(duì)于 Server1 而言顽耳,它的投票是(1, 0)坠敷,接收 Server2的投票為(2, 0),首先會(huì)比較兩者的 ZXID射富,均為 0膝迎,再比較 myid,此時(shí) Server2 的 myid 最大胰耗,于是更新自己的投票為(2, 0)弄抬,然后重新投票,對(duì)于 Server2 而言宪郊,它不需要更新自己的投票掂恕,只是再次向集群中所有機(jī)器發(fā)出上一次投票信息即可。
(4) 統(tǒng)計(jì)投票弛槐。每次投票后懊亡,服務(wù)器都會(huì)統(tǒng)計(jì)投票信息,判斷是否已經(jīng)有過(guò)半機(jī)器接受到相同的投票信息乎串,對(duì)于 Server1店枣、Server2 而言,都統(tǒng)計(jì)出集群中已經(jīng)有兩臺(tái)機(jī)器接受了(2, 0)的投票信息,此時(shí)便認(rèn)為已經(jīng)選出了 Leader鸯两。
(5) 改變服務(wù)器狀態(tài)闷旧。一旦確定了 Leader,每個(gè)服務(wù)器就會(huì)更新自己的狀態(tài)钧唐,如果是 Follower忙灼,那么就變更為FOLLOWING,如果是 Leader钝侠,就變更為 LEADING该园。
運(yùn)行過(guò)程中的 leader 選舉
當(dāng)集群中的 leader 服務(wù)器出現(xiàn)宕機(jī)或者不可用的情況時(shí),那么整個(gè)集群將無(wú)法對(duì)外提供服務(wù)帅韧,而是進(jìn)入新一輪的Leader 選舉里初,服務(wù)器運(yùn)行期間的 Leader 選舉和啟動(dòng)時(shí)期的 Leader 選舉基本過(guò)程是一致的。
(1) 變更狀態(tài)忽舟。Leader 掛后双妨,余下的非 Observer 服務(wù)器都會(huì)將自己的服務(wù)器狀態(tài)變更為 LOOKING,然后開始進(jìn)入 Leader 選舉過(guò)程叮阅。
(2) 每個(gè) Server 會(huì)發(fā)出一個(gè)投票斥难。在運(yùn)行期間,每個(gè)服務(wù)器上的 ZXID 可能不同帘饶,此時(shí)假定 Server1 的 ZXID 為123哑诊,Server3的ZXID為122;在第一輪投票中及刻,Server1和 Server3 都會(huì)投自己镀裤,產(chǎn)生投票(1, 123),(3, 122)缴饭,然后各自將投票發(fā)送給集群中所有機(jī)器暑劝。接收來(lái)自各個(gè)服務(wù)器的投票。與啟動(dòng)時(shí)過(guò)程相同颗搂。
(3) 處理投票担猛。與啟動(dòng)時(shí)過(guò)程相同,此時(shí)丢氢,Server1 將會(huì)成為 Leader傅联。
(4) 統(tǒng)計(jì)投票。與啟動(dòng)時(shí)過(guò)程相同疚察。
(5) 改變服務(wù)器的狀態(tài)蒸走。與啟動(dòng)時(shí)過(guò)程相同
分布式鎖:
基于ZooKeeper的臨時(shí)有序節(jié)點(diǎn)和watch機(jī)制。當(dāng)要獲取鎖時(shí)在某個(gè)目錄下創(chuàng)建一個(gè)臨時(shí)有序節(jié)點(diǎn)貌嫡,每次創(chuàng)建均能成功比驻,只是返回的節(jié)點(diǎn)序號(hào)不同该溯。只有返回的節(jié)點(diǎn)序號(hào)是該目錄下最小的才表示獲取鎖成功,否則表示獲取鎖失敗别惦,此時(shí)watch監(jiān)控節(jié)點(diǎn)序號(hào)比本身小的前一個(gè)節(jié)點(diǎn)狈茉,當(dāng)watch的節(jié)點(diǎn)被刪除后再去嘗試獲取鎖。
優(yōu)缺點(diǎn):
1.Redis分布式鎖需要輪詢獲取鎖掸掸,性能開銷較大氯庆。ZooKeeper分布式鎖基于watch機(jī)制監(jiān)聽節(jié)點(diǎn),不需要輪詢獲取鎖猾漫,性能開銷較小。
2.如果Redis獲取鎖的客戶端非正常退出感凤,那么只能等待超時(shí)時(shí)間之后才能釋放鎖悯周。Redis因?yàn)閯?chuàng)建的是臨時(shí)節(jié)點(diǎn)乌奇,只要客戶端崩潰或者連接斷開晃虫,臨時(shí)節(jié)點(diǎn)就會(huì)被刪除,鎖也就被立即釋放了兔魂。