相信你們最近必定關注到一款重量級消息中間件Kafka發佈了2.8版本,而且正式移除了對Zookeeper的依賴,背後的設計哲學是什麼呢?僅僅只是減小了一個外部依賴嗎?算法
答案顯然不會這麼簡單,容我慢慢道來。微信
在解答爲何以前,我以爲很是有必要先來闡述一下Zookeeper的經典使用場景。架構
一、Zookeeper的經典使用場景
zookeeper是伴隨着大數據、分佈式領域的興起。大數據中的一個很是重要的議題是如何使用衆多廉價的機器來實現可靠存儲。app
所謂廉價的機器就是發生故障的機率很是大,但單臺的成本也很是低,分佈式領域但願使用多臺機器組成一個集羣,將數據存儲在多臺機器上(副本),爲了方便實現數據一致性,一般須要從一個複製組中挑選一臺主節點用戶處理數據的讀寫,其餘節點從主節點拷貝數據,當主節點宕機,須要自動進行從新選舉,實現高可用。運維
上述場景中有一個很是重要的功能Leader選舉,如何選舉出一個主節點、並支持主節點宕機後自動觸發從新選舉,實現主從自動切換,實現高可用。分佈式
使用Zookeeper提供的臨時順序節點與事件監聽機制,能很是輕鬆的實現Leader選舉。 上面的t1,t2能夠理解爲一個組織中的多個成員,能提供相同的服務,但爲了實現冷備效果(即同一時間只有一個成員對外提供服務,咱們稱之爲Leader,當Leader宕機或中止服務後,該組織中的其餘成名從新競爭Leader,而後繼續對外提供服務)。大數據
正如上圖所示,Zookeeper是以集羣部署的,能有效避免單點故障,而且集羣內部提供了對數據的強一致性。url
當成員須要競爭Leader時,藉助Zookeeper的實現套路是向zookeeper中的一個數據節點(示例中爲/app/order-service/leader)節點建立兩個子節點,而且是順序的臨時節點。.net
客戶端判斷建立的節點的序號是否爲/app/order-service/leader中序號最小的節點,若是是則成爲Leader,對外提供服務;設計
若是序號不是最小的,則向本身前置的註冊節點刪除事件,一旦Leader表明的進程宕機,它與Zookeeper的會話失效後,與之關聯的臨時節點會被刪除,一旦Leader建立的節點被刪除,其後繼節點會獲得通知,從而再次觸發選主,選舉出新的Leader,繼續對外提供服務,保質服務的高可用性。
回顧上述場景,藉助Zookeeper能很是輕鬆的實現選主,爲應用提升可用帶來簡便性,主要是利用了Zookeeper的幾個特性:
- 臨時節點 臨時節點是與會話關聯的,一點建立該臨時節點的會話結束,與之會被自動刪除,無需應用方人工刪除。
- 順序節點
- 事件機制 藉助與事件機制,Zookeeper能及時通知存活的其餘應用節點,從新觸發選舉,使得實現自動主從切換變的很是簡單。
二、Kafka對Zookeeper的迫切需求
Kafka中存在衆多的Leader選舉,熟悉Kafka的朋友應該知道,一個主題能夠擁有多個分區(數據分片),每個數據分片能夠配置多個副本,如何保證一個分區的數據在多個副本之間的一致性成爲一個迫切的需求。
Kafka的實現套路就是一個分區的多個副本,從中選舉出一個Leader用來承擔客戶端的讀寫請求,從節點從主節點處拷貝內容,Leader節點根據數據在副本中成功寫入狀況,進行抉擇來肯定是否寫入成功。
Kafka中topic的分區分佈示意圖: 故此處須要進行Leader選舉,而基於Zookeeper能輕鬆實現,今後一拍即合,開啓了一段「蜜月之旅」。
三、Zookeeper的致命弱點
Zookeeper是集羣部署,只要集羣中超過半數節點存活,便可提供服務,例如一個由3個節點的Zookeeper,容許1個Zookeeper節點宕機,集羣仍然能提供服務;一個由5個節點的Zookeeper,容許2個節點宕機。
但Zookeeper的設計是CP模型,即要保證數據的強一致性,必然在可用性方面作出犧牲。
Zookeeper集羣中也存在所謂的Leader節點和從節點,Leader節點負責寫,Leader與從節點可用接受讀請求,但在Zookeeper內部節點在選舉時整個Zookeeper沒法對外提供服務。固然正常狀況下選舉會很是快,但在異常狀況下就很差說了,例如Zookeeper節點發生full Gc,此時形成的影響將是毀滅性的。
Zookeeper節點若是頻繁發生Full Gc,此時與客戶端的會話將超時,因爲此時沒法響應客戶端的心跳請求(Stop World),從而與會話相關聯的臨時節點將被刪除,注意,此時是全部的臨時節點會被刪除,Zookeeper依賴的事件通知機制將失效,整個集羣的選舉服務將失效。
站在高可用性的角度,Kafka集羣的可用性不只取決於自身,還受到了外部組件的制約,從長久來看,顯然都不是一個優雅的方案。
隨着分佈式領域相關技術的不斷完善,去中心化的思想逐步興起,去Zookeeper的呼聲也愈來愈高,在這個進程中涌現了一個很是優秀的算法:Raft協議。
Raft協議的兩個重要組成部分:Leader選舉、日誌複製,而日誌複製爲多個副本提供數據強一致性提供了強一致性,而且一個顯著的特色是Raft節點是去中心化的架構,不依賴外部的組件,而是做爲一個協議簇嵌入到應用中的,即與應用自己是融合爲一體的。
再以Kafka Topic的分佈圖舉例,引用Raft協議的示例圖以下: 關於Raft協議,本文並不打算深刻進行探討,但爲選主提供了另一種可行方案,並且還無需依賴第三方組件,何樂而不爲呢?故最終Kafka在2.8版本中正式廢棄了Zookeeper,擁抱Raft。
若是你們對Raft協議感興趣,推薦閱讀筆者關於Raft協議的系列文章:
好了,本文就介紹到這裏了,鍵三連(關注、點贊、留言)是對我最大的鼓勵,,固然能夠加筆者微信:dingwpmz,備註CSDN,共同交流探討。
最後分享筆者一個硬核的RocketMQ電子書,您將得到千億級消息流轉的運維經驗。 獲取方式:微信搜索【中間件興趣圈】,回覆RMQPDF便可獲取。