根據前面的介紹,咱們已經大概瞭解了Kafka也是一款性能很是好的而且支持分佈式的消息隊列中間件。因爲它的高吞吐特性,Kafka一般使用在大數據領域,如日誌收集平臺。其實Kafka是一個流處理平臺,這個概念不太好理解,之因此叫作流,是由於它在工做中就像是一個能夠支撐高吞吐量的管道,數據像水同樣流進去,而後另一端再去讀取這些數據。咱們就能夠把Kafka看做是一種特殊的消息隊列中間件。node
Kafka與傳統消息系統相比,有如下不一樣:linux
它被設計爲一個分佈式系統,易於向外擴展; 它同時爲發佈和訂閱提供高吞吐量; 它支持多訂閱者,當失敗時能自動平衡消費者; 它將消息持久化到磁盤,所以可用於批量消費,例如ETL,以及實時應用程序。
在Kafka中有幾個關鍵角色和概念。git
Producergithub
消息生產者,是消息的產生源頭,負責生成消息併發送給Kafka。apache
Consumer服務器
消息消費者,是消息的使用方,負責消費Kafka服務器上的消息。數據結構
Topic併發
主題,由用戶自定義,並配置在Kafka服務器,用於創建生產者和消費者之間的訂閱關係,生產者將消息發送到指定的Topic,而後消費者再從該Topic下去取消息。負載均衡
Partition框架
消息分區,一個Topic下面會有多個Partition,每一個Partition都是一個有序隊列,Partition中的每條消息都會被分配一個有序的id。
Broker
這個其實就是Kafka服務器了,不管是單臺Kafka仍是集羣,被統一叫作Broker,有的資料上把它翻譯爲代理或經紀人。
Group
消費者分組,將同一類的消費者歸類到一個組裏。在Kafka中,多個消費者共同消費一個Topic下的消息,每一個消費者消費其中的部分消息,這些消費者就組成了一個分組,擁有同一個組名。
官網:http://zookeeper.apache.org/
Kafka的運行依賴ZooKeeper。ZooKeeper是一個分佈式協調服務,它的主要做用是爲分佈式系統提供一致性服務,提供的功能包括:配置維護、命名服務、分佈式同步、組服務等。
ZooKeeper最先起源於雅虎研究院的一個研究小組。在當時,研究人員發現,在雅虎內部不少大型系統基本都須要依賴一個相似的系統來進行分佈式協調,可是這些系統每每都存在分佈式單點問題。因此,雅虎的開發人員就試圖開發一個通用的無單點問題的分佈式協調框架,以便讓開發人員將精力集中在處理業務邏輯上。
關於ZooKeeper這個項目的名字,其實也有一段趣聞。在立項初期,考慮到以前內部不少項目都是使用動物的名字來命名的(例如著名的Pig項目),雅虎的工程師但願給這個項目也取一個動物的名字。時任研究院的首席科學家RaghuRamakrishnan開玩笑地說:「在這樣下去,咱們這兒就變成動物園了!」此話一出,你們紛紛表示就叫動物園管理員吧 一一 由於各個以動物命名的分佈式組件放在一塊兒,雅虎的整個分佈式系統看上去就像一個大型的動物園了,而ZooKeeper正好要用來進行分佈式環境的協調。因而,ZooKeeper的名字也就由此誕生了。
相似於Linux的文件系統,是一種樹形的結構。以下:
/ / \ / \ Lang Service / \ / \ / \ / \ JAVA PHP Nginx Tomcat
若是已經搭建了ZooKeeper服務,能夠進入到ZooKeeper命令行終端,而後執行ls /看到下面的目錄結構
/usr/local/zookeeper/bin/zkCli.sh -server aming01:2181 進入到Zookeeper的命令行終端下面,執行:ls /
樹是由節點所組成,ZooKeeper的數據存儲也一樣是基於節點,這種節點叫作Znode。/Lang/PHP是一個節點,/Service/Tomcat也是一個節點,這樣就可讓每個Znode擁有惟一的路徑。每個Znode裏包含了數據、子節點引用、訪問權限等。
如上圖,data即Znode裏面的數據,ACL爲權限規則,它規定了哪些用戶或哪些IP纔有權限訪問此Znode,stat記錄了Znode相關的元數據,好比事務ID、版本號、時間戳、大小,child爲當前節點的子節點引用,相似於二叉樹的左孩子右孩子。ZooKeeper有個限制,每一個Znode的數據大小不會超過1M。
get /node_name getAcl /node_name
持久節點(PERSISTENT)
所謂持久節點,是指在節點建立後,就一直存在,直到有刪除操做來主動清除這個節點——不會由於建立該節點的客戶端會話失效而消失。
create /node 'persistent node'
持久順序節點(PERSISTENT_SEQUENTIAL,節點會自動加上編號)
這類節點的基本特性和上面的節點類型是一致的。額外的特性是,在ZK中,每一個父節點會爲他的第一級子節點維護一份時序,會記錄每一個子節點建立的前後順序。基於這個特性,在建立子節點的時候,能夠設置這個屬性,那麼在建立節點過程當中,ZK會自動爲給定節點名加上一個數字後綴,做爲新的節點名。這個數字後綴的範圍是整型的最大值。
在建立節點的時候只須要傳入節點 「/test_」,這樣以後,zookeeper自動會給」test_」後面補充數字。
create -s /s_node 'persistent sequential'
臨時節點(EPHEMERAL)
和持久節點不一樣的是,臨時節點的生命週期和客戶端會話綁定。也就是說,若是客戶端會話失效,那麼這個節點就會自動被清除掉。注意,這裏提到的是會話失效,而非鏈接斷開。另外,在臨時節點下面不能建立子節點。
這裏還要注意一件事,就是當你客戶端會話失效後,所產生的節點也不是一會兒就消失了,也要過一段時間,大概是10秒之內,本機操做生成節點,在服務器端用命令來查看當前的節點數目,你會發現客戶端已經stop,可是產生的節點還在。
create -e /e_node 'ephemeral'
臨時順序節點(EPHEMERAL_SEQUENTIAL)
此節點是屬於臨時節點,不過帶有順序,客戶端會話結束節點就消失。下面是一個利用該特性的分佈式鎖的案例流程。
create -e -s /e_s_node 'ephemeral sequential'
ZooKeeper提供服務時,是須要經過集羣來實現,ZooKeeper集羣中有一個leader,多個follower角色,其中leader提供寫服務,follower提供讀服務。
Leader是整個ZooKeeper集羣工做機制中的核心 。Leader做爲整個ZooKeeper集羣的主節點,負責響應全部對ZooKeeper狀態變動的請求。其主要工做包括下面兩個方面
1)事務請求的惟一調度和處理,保障集羣處理事務的順序性。
2)集羣內各服務器的調度者。
Leader選舉是ZooKeeper最重要的技術之一,也是保障分佈式數據一致性的關鍵所在。咱們以三臺機器爲例,在服務器集羣初始化階段,當有一臺服務器Server1啓動時候是沒法完成選舉的,當第二臺機器Server2啓動後兩臺機器能互相通訊,每臺機器都試圖找到一個leader,因而便進入了leader選舉流程.
每一個server發出一個投票,投票的最基本元素是SID(服務器id)和ZXID(事物id)--> 接受來自各個服務器的投票 --> 處理投票,優先檢查ZXID(數據越新ZXID越大),ZXID比較大的做爲leader,ZXID同樣的狀況下比較SID --> 統計投票,這裏有個過半的概念,大於集羣機器數量的一半,即大於或等於(n/2+1),咱們這裏是三臺,因此大於等於2即爲達到「過半」的要求 --> 改變服務器狀態,一旦肯定了leader,服務器就會更改本身的狀態,且通常不會再發生變化。
Follower即跟隨者,他的邏輯比較簡單。除了響應本服務器上的讀請求外,還要處理leader的提議,並在leader提交該提議時在本地也進行提交。另外須要注意的是,leader和follower構成ZooKeeper集羣的法定人數,也就是說,只有他們才參與新leader的選舉、響應leader的提議。
服務器充當一個觀察者的角色。若是ZooKeeper集羣的讀取負載很高,或者客戶端多到跨機房,能夠設置一些observer服務器,以提升讀取的吞吐量。Observer和Follower比較類似,只有一些小區別:首先observer不屬於法定人數,即不參加選舉也不響應提議,也不參與寫操做的「過半寫成功」策略;其次是observer不須要將事務持久化到磁盤,一旦observer被重啓,須要從leader從新同步整個命名空間。
咱們瞭解了ZooKeeper的分佈式協調服務特性後,再來看看Zookeeper在Kafka集羣中到底擔任了一個什麼樣的角色?
簡單講,ZooKeeper用於分佈式系統的協調,Kafka使用ZooKeeper也是基於相同的緣由。ZooKeeper主要用來協調Kafka的各個broker,不只能夠實現broker的負載均衡,並且當增長了broker或者某個broker故障了,ZooKeeper將會通知生產者和消費者,這樣能夠保證整個系統正常運轉。
Broker註冊
Broker在ZooKeeper中保存爲一個臨時節點,節點的路徑是/brokers/ids/[brokerid],每一個節點會保存對應broker的IP以及端口等信息.
/usr/local/zookeeper/bin/zkCli.sh -server aming01:2181 進入到Zookeeper的命令行終端下面,執行:ls /brokers/ids
Topic註冊
在Kafka中,一個topic會被分紅多個區並被分到多個broker上,分區的信息以及broker的分佈狀況都保存在ZooKeeper中,根節點路徑爲/brokers/topics,每一個topic都會在topics下創建獨立的子節點,每一個topic節點下都會包含分區以及broker的對應信息
/usr/local/zookeeper/bin/zkCli.sh -server aming01:2181 進入到Zookeeper的命令行終端下面,執行:ls /brokers/topics
生產者負載均衡
當Broker啓動時,會註冊該Broker的信息,以及可訂閱的topic信息。生產者經過註冊在Broker以及Topic上的watcher動態的感知Broker以及Topic的分區狀況,從而將Topic的分區動態的分配到broker上.
ls2 /brokers/topics watch
消費者
Kafka有消費者分組的概念,每一個分組中能夠包含多個消費者,每條消息只會發給分組中的一個消費者,且每一個分組之間是相互獨立互不影響的。
消費者與分區的對應關係
對於每一個消費者分組,Kafka都會爲其分配一個全局惟一的Group ID,分組內的全部消費者會共享該ID, Kafka還會爲每一個消費者分配一個consumer ID,一般採用hostname:uuid的形式。在kafka的設計中規定,對於topic的每一個分區,最多隻能被一個消費者進行消費,也就是消費者與分區的關係是一對多的關係。消費者與分區的關係也被存儲在ZooKeeper中節點的路勁爲 /consumers/[group_id]/owners/[topic]/[broker_id-partition_id],該節點的內容就是消費者的Consumer ID
消費者負載均衡
消費者服務啓動時,會建立一個屬於消費者節點的臨時節點,節點的路徑爲 /consumers/[group_id]/ids/[consumer_id],該節點的內容是該消費者訂閱的Topic信息。每一個消費者會對/consumers/[group_id]/ids節點註冊Watcher監聽器,一旦消費者的數量增長或減小就會觸發消費者的負載均衡。消費者還會對/brokers/ids/[brokerid]節點進行監聽,若是發現服務器的Broker服務器列表發生變化,也會進行消費者的負載均衡
消費者的offset
在Kafka的消費者API分爲兩種(1)High Level Api:由ZooKeeper維護消費者的offset (2) Low Level API,本身的代碼實現對offset的維護。因爲本身維護offset每每比較複雜,因此多數狀況下都是使用High Level的API, offset在ZooKeeper中的節點路徑爲/consumers/[group_id]/offsets/[topic]/[broker_id-part_id],該節點的值就是對應的offset
1)生產者按期向主題發送消息。
2)Kafka broker將全部消息存儲在爲該特定主題配置的分區中。它確保消息在分區之間平等共享。若是生產者發送兩個消息,而且有兩個分區,則Kafka將在第一個分區中存儲一個消息,在第二個分區中存儲第二個消息。
3)消費者訂閱一個特定的主題。
4)一旦消費者訂閱了一個主題,Kafka將向消費者提供該主題的當前偏移量,並將偏移量保存在ZooKeeper中。
5)消費者將按期請求Kafka新消息。
6)一旦Kafka收到來自生產者的消息,它會將這些消息轉發給消費者。
7)消費者將收到消息並處理它。
8)一旦消息被處理,消費者將向Kafka broker發送確認。
9)一旦Kafka收到確認,它會將偏移量更改成新值,並在ZooKeeper中進行更新。因爲ZooKeeper中保留了偏移量,所以即便在服務器出現故障時,消費者也能夠正確讀取下一條消息。