1. 程式人生 > >ZooKeeper and kafka

ZooKeeper and kafka

文章目錄

ZooKeeper 基本概念

ZooKeeper 一個最常用的使用場景就是用於擔任服務生產者和服務消費者的註冊中心。

服務生產者將自己提供的服務註冊到 ZooKeeper 中心,服務的消費者在進行服務呼叫的時候先到 ZooKeeper 中查詢服務,獲取到服務生產者的詳細資訊之後,再去呼叫服務生產者的內容與資料。
reg

ZooKeeper 主要提供下面幾個功能:

  • 叢集管理:容錯、負載均衡。
  • 配置檔案的集中管理。
  • 叢集的入口。
    重要概念總結

關於 ZooKeeper 的一些重要概念:

  • ZooKeeper 本身就是一個分散式程式(只要半數以上節點存活,ZooKeeper 就能正常服務)。
  • 為了保證高可用,最好是以叢集形態來部署 ZooKeeper,這樣只要叢集中大部分機器是可用的(能夠容忍一定的機器故障),那麼 ZooKeeper 本身仍然是可用的。
  • ZooKeeper 將資料儲存在記憶體中,這也就保證了 高吞吐量和低延遲(但是記憶體限制了能夠儲存的容量不太大,此限制也是保持 Znode 中儲存的資料量較小的進一步原因)。
  • ZooKeeper 是高效能的。在“讀”多於“寫”的應用程式中尤其地高效能,因為“寫”會導致所有的伺服器間同步狀態。(“讀”多於“寫”是協調服務的典型場景。)
  • ZooKeeper 有臨時節點的概念。當建立臨時節點的客戶端會話一直保持活動,瞬時節點就一直存在。
    而當會話終結時,瞬時節點被刪除。持久節點是指一旦這個 ZNode 被建立了,除非主動進行 ZNode 的移除操作,否則這個 ZNode 將一直儲存在 Zookeeper 上。
  • ZooKeeper 底層其實只提供了兩個功能:①管理(儲存、讀取)使用者程式提交的資料;②為使用者程式提交資料節點監聽服務。

ZooKeeper 特點

ZooKeeper 有哪些特點呢?具體如下:

  • 順序一致性:從同一客戶端發起的事務請求,最終將會嚴格地按照順序被應用到 ZooKeeper 中去。
  • 原子性:所有事務請求的處理結果在整個叢集中所有機器上的應用情況是一致的,也就是說,要麼整個叢集中所有的機器都成功應用了某一個事務,要麼都沒有應用。
  • 單一系統映像:無論客戶端連到哪一個 ZooKeeper 伺服器上,其看到的服務端資料模型都是一致的。
  • 可靠性:一旦一次更改請求被應用,更改的結果就會被持久化,直到被下一次更改覆蓋。

kafka簡介

Kafka是linkedin開源的MQ系統,主要特點是基於Pull的模式來處理訊息消費,追求高吞吐量,一開始的目的就是用於日誌收集和傳輸,0.8開始支援複製,不支援事務,適合產生大量資料的網際網路服務的資料收集業務。

RabbitMQ/Kafka/ZeroMQ 都能提供訊息佇列服務,但有很大的區別。

在面向服務架構中通過訊息代理(比如 RabbitMQ / Kafka等),使用生產者-消費者模式在服務間進行非同步通訊是一種比較好的思想。

因為服務間依賴由強耦合變成了鬆耦合。訊息代理都會提供持久化機制,在消費者負載高或者掉線的情況下會把訊息儲存起來,不會丟失。就是說生產者和消費者不需要同時線上,這是傳統的請求-應答模式比較難做到的,需要一箇中間件來專門做這件事。其次訊息代理可以根據訊息本身做簡單的路由策略,消費者可以根據這個來做負載均衡,業務分離等。

缺點也有,就是需要額外搭建訊息代理叢集(但優點是大於缺點的 ) 。

ZeroMQ 和 RabbitMQ/Kafka 不同,它只是一個非同步訊息庫,在套接字的基礎上提供了類似於訊息代理的機制。使用 ZeroMQ 的話,需要對自己的業務程式碼進行改造,不利於服務解耦。ZeroMQ僅提供非永續性的佇列,也就是說如果宕機,資料將會丟失。

RabbitMQ 支援 AMQP(二進位制),STOMP(文字),MQTT(二進位制),HTTP(裡面包裝其他協議)等協議。Kafka 使用自己的協議。

Kafka 自身服務和消費者都需要依賴 Zookeeper。

RabbitMQ 在有大量訊息堆積的情況下效能會下降,Kafka不會。畢竟AMQP設計的初衷不是用來持久化海量訊息的,而Kafka一開始是用來處理海量日誌的。
RabbitMQ和Kafka基本上是一類東西,各有優劣,ZeroMQ只是一個網路庫,不支援持久化。

基本術語

  • Topic
    Kafka中的topic其實對應傳統MQ的channel,即訊息管道,例如同一業務用同一根管道
  • Broker
    叢集中的KafkaServer,用來提供Partition服務
  • Partition
    假如說傳統的MQ,傳輸訊息的通道(channel)是一條雙車道公路,那麼Kafka中,Topic就是一個N車道的高速公路。每個車道都可以行車,而每個車道就是Partition。
    • 一個Topic中可以有一個或多個partition。
    • 一個Broker上可以跑一個或多個Partition。叢集中儘量保證partition的均勻分佈,例如定義了一個有3個partition的topic,而只有兩個broker,那麼一個broker上跑兩個partition,而另一個是1個。但是如果有3個broker,必然是3個broker上各跑一個partition。
    • Partition中嚴格按照訊息進入的順序排序
    • 一個從Producer傳送來的訊息,只會進入Topic的某一個Partition(除非特殊實現Producer要求訊息進入所有Partition)
    • Consumer可以自己決定從哪個Partition讀取資料
  • Offset
    單個Partition中的訊息的順序ID,例如第一個進入的Offset為0,第二個為1,以此類推。傳統的MQ,Offset是由MQ自己維護,而kafka是由client維護
  • Replica
    Kafka從0.8版本開始,支援訊息的HA,通過訊息複製的方式。在建立時,我們可以指定一個topic有幾個partition,以及每個partition有幾個複製。複製的過程有同步和非同步兩種,根據效能需要選取。正常情況下,寫和讀都是訪問leader,只有當leader掛掉或者手動要求重新選舉,kafka會從幾個複製中選舉新的leader。
    Kafka會統計replica與leader的同步情況。當一個replica與leader資料相差不大,會被認為是一個"in-sync" replica。只有"in-sync" replica才有資格參與重新選舉。
  • ConsumerGroup
    一個或多個Consumer構成一個ConsumerGroup,一個訊息應該只能被同一個ConsumerGroup中的一個Consumer消化掉,但是可以同時傳送到不同ConsumerGroup。
    通常的做法,一個Consumer去對應一個Partition。
    傳統MQ中有queuing(訊息)和publish-subscribe(訂閱)模式,Kafka中也支援:
    • 當所有Consumer具有相同的ConsumerGroup時,該ConsumerGroup中只有一個Consumer能收到訊息,就是queuing模式
    • 當所有Consumer具有不同的ConsumerGroup時,每個ConsumerGroup會收到相同的訊息,就是publish-subscribe模式

topic中partition儲存分佈

Topic在邏輯上可以被認為是一個queue。每條消費都必須指定它的topic,可以簡單理解為必須指明把這條訊息放進哪個queue裡。為了使得 Kafka的吞吐率可以水平擴充套件,物理上把topic分成一個或多個partition,每個partition在物理上對應一個資料夾,該資料夾下儲存 這個partition的所有訊息和索引檔案。partiton命名規則為topic名稱+有序序號,第一個partiton序號從0開始,序號最大值為partitions數量減1。

基本互動原理

每個Topic被建立後,在zookeeper上存放有其metadata,包含其分割槽資訊、replica資訊、LogAndOffset等,並使用了zookeeper watch機制來發現meta資訊的變更並作出相應的動作(比如consumer失效,觸發負載均衡等)

Producer端使用zookeeper用來"發現"broker列表,以及和Topic下每個partition leader建立socket連線併發送訊息.
Broker端使用zookeeper用來註冊broker資訊,已經監測partitionleader存活性.
Consumer端使用zookeeper用來註冊consumer資訊,其中包括consumer消費的partition列表等,同時也用來發現broker列表,並和partition leader建立socket連線,並獲取訊息.

  1. Broker node registry: 當一個kafkabroker啟動後,首先會向zookeeper註冊自己的節點資訊(臨時znode),同時當broker和zookeeper斷開連線時,此znode也會被刪除.
    格式: /broker/ids/[0…N] -->host:port;其中[0…N]表示broker id,每個broker的配置檔案中都需要指定一個數字型別的id(全域性不可重複),znode的值為此broker的host:port資訊.
  2. Broker Topic Registry: 當一個broker啟動時,會向zookeeper註冊自己持有的topic和partitions資訊,仍然是一個臨時znode.
    格式: /broker/topics/[topic]/[0…N] 其中[0…N]表示partition索引號.
  3. Consumer and Consumer group: 每個consumer客戶端被建立時,會向zookeeper註冊自己的資訊;此作用主要是為了"負載均衡".

Kakfa Broker Leader的選舉

Kakfa Broker叢集受Zookeeper管理。所有的Kafka Broker節點一起去Zookeeper上註冊一個臨時節點,因為只有一個Kafka Broker會註冊成功,其他的都會失敗,所以這個成功在Zookeeper上註冊臨時節點的這個Kafka Broker會成為Kafka Broker Controller,其他的Kafka broker叫Kafka Broker follower。(這個過程叫Controller在ZooKeeper註冊Watch)。這個Controller會監聽其他的Kafka Broker的所有資訊,如果這個kafka broker controller宕機了,在zookeeper上面的那個臨時節點就會消失,此時所有的kafka broker又會一起去Zookeeper上註冊一個臨時節點,因為只有一個Kafka Broker會註冊成功,其他的都會失敗,所以這個成功在Zookeeper上註冊臨時節點的這個Kafka Broker會成為Kafka Broker Controller,其他的Kafka broker叫Kafka Broker follower。例如:一旦有一個broker宕機了,這個kafka broker controller會讀取該宕機broker上所有的partition在zookeeper上的狀態,並選取ISR列表中的一個replica作為partition leader(如果ISR列表中的replica全掛,選一個倖存的replica作為leader; 如果該partition的所有的replica都宕機了,則將新的leader設定為-1,等待恢復,等待ISR中的任一個Replica“活”過來,並且選它作為Leader;或選擇第一個“活”過來的Replica(不一定是ISR中的)作為Leader),這個broker宕機的事情,kafka controller也會通知zookeeper,zookeeper就會通知其他的kafka broker。