Kafka與ActiveMQ區別

Kafka 是LinkedIn 開發的一個高性能、分佈式的消息系統,廣泛用於日誌收集、流式數據處理、在線和離線消息分發等場景。雖然不是作爲傳統的MQ來設計,在大部分情況,Kafaka 也可以代替原先ActiveMQ 等傳統的消息系統。

Kafka 將消息流按Topic 組織,保存消息的服務器稱爲Broker,消費者可以訂閱一個或者多個Topic。爲了均衡負載,一個Topic 的消息又可以劃分到多個分區(Partition),分區越多,Kafka並行能力和吞吐量越高。

Kafka 集羣需要zookeeper 支持來實現集羣,最新的kafka 發行包中已經包含了zookeeper,部署的時候可以在一臺服務器上同時啓動一個zookeeper Server 和 一個Kafka Server,也可以使用已有的其他zookeeper集羣。

和傳統的MQ不同,消費者需要自己保留一個offset,從kafka 獲取消息時,只拉去當前offset 以後的消息。Kafka 的scala/java 版的client 已經實現了這部分的邏輯,將offset 保存到zookeeper 上。每個消費者可以選擇一個id,同樣id 的消費者對於同一條消息只會收到一次。一個Topic 的消費者如果都使用相同的id,就是傳統的 Queue;如果每個消費者都使用不同的id, 就是傳統的pub-sub.

如果在MQ的場景下,將Kafka 和 ActiveMQ 相比:

Kafka 的優點

分佈式可高可擴展。Kafka 集羣可以透明的擴展,增加新的服務器進集羣。

高性能。Kafka 的性能大大超過傳統的ActiveMQ、RabbitMQ等MQ 實現,尤其是Kafka 還支持batch 操作。下圖是linkedin 的消費者性能壓測結果:

容錯。Kafka每個Partition的數據都會複製到幾臺服務器上。當某個Broker故障失效時,ZooKeeper服務將通知生產者和消費者,生產者和消費者轉而使用其它Broker。

Kafka 的不利

重複消息。Kafka 只保證每個消息至少會送達一次,雖然機率很小,但一條消息有可能會被送達多次。 
消息亂序。雖然一個Partition 內部的消息是保證有序的,但是如果一個Topic 有多個Partition,Partition 之間的消息送達不保證有序。 
複雜性。Kafka需要zookeeper 集羣的支持,Topic通常需要人工來創建,部署和維護較一般消息隊列成本更高

=-=======================================================================

 

00

今天讓我們來談談身份高貴,舉止優雅的消息中間件,主要還是淺談,消息中間件這塊水太深。大體上我們結合互聯網業務做一些探討,從互聯網主要關心的消息安全性,服務器的穩定性容錯性以及吞吐量三方面來講。

由於這塊產品非常多,我只挑選兩個我使用過的產品結合使用經驗做一些研究,他們是ActiveMQ和Kafka,前者完全實現了JMS的規範,後者看上去有一些“野路子”,並沒有糾結於JMS規範,劍走偏鋒的設計了另一套吞吐非常高的分佈式發佈-訂閱消息系統,目前非常流行。接下來我們結合三個點(消息安全性,服務器的穩定性容錯性以及吞吐量)來分別談談這兩個消息中間件。今天我們談Kafka,ActiveMQ的文章在此。

01 性能怪獸Kafka

Kafka是LinkedIn開源的分佈式發佈-訂閱消息系統,目前歸屬於Apache定級項目。”Apache Kafka is publish-subscribe messaging rethought as a distributed commit log.”,官網首頁的一句話高度概括其職責。Kafka並沒有遵守JMS規範,他只用文件系統來管理消息的生命週期。Kafka的設計目標是:

(1)以時間複雜度爲O(1)的方式提供消息持久化能力,即使對TB級以上數據也能保證常數時間複雜度的訪問性能。

(2)高吞吐率。即使在非常廉價的商用機器上也能做到單機支持每秒100K條以上消息的傳輸。

(3)支持Kafka Server間的消息分區,及分佈式消費,同時保證每個Partition內的消息順序傳輸。

(4)同時支持離線數據處理和實時數據處理。

(5)Scale out:支持在線水平擴展。

所以,不像AMQ,Kafka從設計開始極爲高可用爲目的,天然HA。broker支持集羣,消息亦支持負載均衡,還有副本機制。同樣,Kafka也是使用Zookeeper管理集羣節點信息,包括consumer的消費信息也是保存在zk中,下面我們分話題來談:

1)消息的安全性

Kafka集羣中的Leader負責某一topic的某一partition的消息的讀寫,理論上consumer和producer只與該Leader節點打交道,一個集羣裏的某一broker即是Leader的同時也可以擔當某一partition的follower,即Replica。Kafka分配Replica的算法如下:

(1)將所有Broker(假設共n個Broker)和待分配的Partition排序

(2)將第i個Partition分配到第(i mod n)個Broker上

(3)將第i個Partition的第j個Replica分配到第((i + j) mode n)個Broker上

同時,Kafka與Replica既非同步也不是嚴格意義上的異步。一個典型的Kafka發送-消費消息的過程如下:首先首先Producer消息發送給某Topic的某Partition的Leader,Leader先是將消息寫入本地Log,同時follower(如果落後過多將會被踢出出Replica列表)從Leader上pull消息,並且在未寫入log的同時即向Leader發送ACK的反饋,所以對於某一條已經算作commit的消息來講,在某一時刻,其存在於Leader的log中,以及Replica的內存中。這可以算作一個危險的情況(聽起來嚇人),因爲如果此時集羣掛了這條消息就算丟失了,但結合producer的屬性(request.required.acks=2 當所有follower都收到消息後返回ack)可以保證在絕大多數情況下消息的安全性。當消息算作commit的時候纔會暴露給consumer,並保證at-least-once的投遞原則。

2)服務的穩定容錯性

前面提到過,Kafka天然支持HA,整個leader/follower機制通過zookeeper調度,它在所有broker中選出一個controller,所有Partition的Leader選舉都由controller決定,同時controller也負責增刪Topic以及Replica的重新分配。如果Leader掛了,集羣將在ISR(in-sync replicas)中選出新的Leader,選舉基本原則是:新的Leader必須擁有原來的Leader commit過的所有消息。假如所有的follower都掛了,Kafka會選擇第一個“活”過來的Replica(不一定是ISR中的)作爲Leader,因爲如果此時等待ISR中的Replica是有風險的,假如所有的ISR都無法“活”,那此partition將會變成不可用。

3) 吞吐量

Leader節點負責某一topic(可以分成多個partition)的某一partition的消息的讀寫,任何發佈到此partition的消息都會被直接追加到log文件的尾部,因爲每條消息都被append到該partition中,是順序寫磁盤,因此效率非常高(經驗證,順序寫磁盤效率比隨機寫內存還要高,這是Kafka高吞吐率的一個很重要的保證),同時通過合理的partition,消息可以均勻的分佈在不同的partition裏面。Kafka基於時間或者partition的大小來刪除消息,同時broker是無狀態的,consumer的消費狀態(offset)是由consumer自己控制的(每一個consumer實例只會消費某一個或多個特定partition的數據,而某個partition的數據只會被某一個特定的consumer實例所消費),也不需要broker通過鎖機制去控制消息的消費,所以吞吐量驚人,這也是Kafka吸引人的地方。

最後說下由於zookeeper引起的腦裂(Split Brain)問題:每個consumer分別單獨通過Zookeeper判斷哪些partition down了,那麼不同consumer從Zookeeper“看”到的view就可能不一樣,這就會造成錯誤的reblance嘗試。而且有可能所有的consumer都認爲rebalance已經完成了,但實際上可能並非如此。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章