架構師的選擇,Kafka還是Rabbit MQ

架構師的困境

架構師的選擇,Kafka還是Rabbit MQ

Photo by Justin Luebke on Unsplash

介紹

作為處理許多基於微服務的系統的軟件架構師,我經常遇到一個不斷重複的問題:"我應該使用RabbitMQ還是Kafka?" 由於某些原因,許多開發人員認為這些技術是可互換的。 儘管在某些情況下確實如此,但這些平臺之間存在各種潛在的差異。

結果,不同的方案需要不同的解決方案,選擇錯誤的方案可能會嚴重影響您設計,開發和維護軟件解決方案的能力。

本文的目的是首先介紹基本的異步消息傳遞模式。 然後,它將繼續介紹RabbitMQ和Kafka及其內部結構。 第2部分將重點介紹這些平臺之間的關鍵區別,它們的各種優缺點以及如何在兩者之間進行選擇。

異步消息傳遞模式

異步消息傳遞是一種消息傳遞方案,其中生產者的消息生產與消費者的消息處理不相關。 在處理消息傳遞系統時,我們通常會確定兩種主要的消息傳遞模式-消息排隊和發佈/訂閱。

消息隊列

在消息隊列通信模式中,隊列在時間上使生產者與消費者脫鉤。 多個生產者可以將消息發送到同一隊列。 但是,當使用者處理郵件時,該郵件將被鎖定或從隊列中刪除,並且不再可用。 只有一個消費者消費一條特定的消息。

架構師的選擇,Kafka還是Rabbit MQ

Message queuing


附帶說明一下,如果使用者無法處理某條消息,則消息傳遞平臺通常會將消息返回到隊列中,以供其他使用者使用。 除了臨時解耦,隊列還使我們能夠獨立地擴展生產者和消費者的規模,並提供一定程度的容錯能力以應對處理錯誤。

發佈/訂閱

在發佈/訂閱(或pub / sub)通信模式中,多個訂戶可以同時接收和處理一條消息。

架構師的選擇,Kafka還是Rabbit MQ

Publish/subscribe

例如,此模式允許發佈者通知所有訂閱者系統中發生了某些事情。 許多排隊平臺通常將pub / sub與術語主題相關聯。 在RabbitMQ中,主題是pub / sub實現的一種特定類型(確切地說是一種交換類型),但是在本篇文章中,我將主題稱為pub / sub整體的表示。

一般而言,訂閱有兩種類型:

· 臨時訂閱,僅在使用者啟動並運行時,訂閱才處於活動狀態。 使用者關閉後,其訂閱和尚未處理的消息就會丟失。

· 長期訂閱,只要未明確刪除訂閱,訂閱就會一直保留。 當使用者關閉時,消息傳遞平臺將維護訂閱,並且稍後可以恢復消息處理。

RabbitMQ

RabbitMQ是消息代理的實現,通常稱為服務總線。 它本身支持上述兩種消息傳遞模式。 消息代理的其他流行實現包括ActiveMQ,ZeroMQ,Azure服務總線和Amazon Simple Queue Service(SQS)。 所有這些實現都有很多共同點。 本文中描述的許多概念都適用於大多數概念。

消息隊列

RabbitMQ支持開箱即用的經典消息隊列。 開發人員定義命名隊列,然後發佈者可以將消息發送到該命名隊列。 消費者進而使用相同的隊列來檢索消息以對其進行處理。

信息交流

RabbitMQ通過使用消息交換來實現pub / sub。 發佈者將其消息發佈到消息交換,而不知道這些消息的訂閱者是誰。

每個希望訂閱交換的消費者都會創建一個隊列。 然後,消息交換將產生的消息排隊,以供消費者使用。 它還可以基於各種路由規則為某些訂戶過濾消息。

架構師的選擇,Kafka還是Rabbit MQ

RabbitMQ message exchange

請務必注意,RabbitMQ支持臨時訂閱和持久訂閱。 消費者可以通過RabbitMQ的API決定要使用的訂閱類型。

由於RabbitMQ的體系結構,我們還可以創建一種混合方法-一些訂戶形成消費者組,這些消費者組以特定隊列中競爭的消費者的形式一起處理消息。 通過這種方式,我們實現了發佈/訂閱模式,同時還允許某些訂閱者擴大規模以處理收到的消息。

架構師的選擇,Kafka還是Rabbit MQ

Pub/sub and queuing combined


Apache Kafka

Apache Kafka不是消息代理的實現。 而是一個分佈式流媒體平臺。

與基於隊列和交換的RabbitMQ不同,Kafka的存儲層是使用分區的事務日誌實現的。 Kafka還提供用於實時處理流的Streams API和可輕鬆與各種數據源集成的Connector API。 但是,這些不在本文的討論範圍之內。

雲供應商為Kafka的存儲層提供了替代解決方案。 這些解決方案包括Azure事件中心,在某種程度上還包括AWS Kinesis數據流。 Kafka的流處理功能也有特定於雲的開源替代方案,但是同樣,這些不在本文的討論範圍之內。

話題 Topic

Kafka沒有實現隊列的概念。 相反,Kafka將記錄的集合存儲在稱為主題的類別中。

對於每個主題,Kafka維護消息的分區日誌。 每個分區都是一個有序的,不可變的記錄序列,在該記錄中連續附加消息。

當這些分區到達時,Kafka會將消息附加到這些分區。 默認情況下,它使用循環分區程序在各個分區之間均勻分佈消息。

生產者可以修改此行為以創建消息的邏輯流。 例如,在多租戶應用程序中,我們可能想根據每個消息的租戶ID創建邏輯消息流。 在物聯網場景中,我們可能希望不斷將每個生產者的身份映射到特定分區。 確保來自同一邏輯流的所有消息都映射到同一分區,以確保將其傳遞給消費者。

架構師的選擇,Kafka還是Rabbit MQ

Kafka producers

使用者通過維持這些分區的偏移量(或索引)並順序讀取它們來消費消息。

單個使用者可以使用多個主題,並且使用者可以擴展到可用分區的數量。

因此,在創建主題時,應仔細考慮該主題上消息傳遞的預期吞吐量。 一起工作以消費主題的一組消費者稱為消費群體。 Kafka的API通常會處理消費者組中消費者之間的分區處理與消費者當前分區偏移量的存儲之間的平衡。

架構師的選擇,Kafka還是Rabbit MQ

Kafka consumers


使用Kafka實現消息傳遞模式

Kafka的實現非常適合pub / sub模式。

生產者可以將消息發送到特定主題,而多個消費者組可以使用同一條消息。 每個消費者組可以單獨擴展以處理負載。 由於使用者維護其分區偏移量,因此他們可以選擇具有持久性的訂閱,該持久性訂閱在重新啟動或臨時訂閱期間保持其偏移量,這將丟棄偏移量,並在每次啟動時從每個分區中的最新記錄重新啟動。

但是,它不適用於消息隊列模式。 當然,我們可以只包含一個消費者組來模擬一個經典消息隊列。 然而,這有多個缺點。本文的第2部分將詳細討論。

請務必注意,Kafka會將郵件保留在分區中,直到預定的時間,無論消費者是否消費了這些郵件。 這種保留意味著消費者可以自由地重讀過去的消息。 此外,開發人員還可以使用Kafka的存儲層來實現各種機制,例如事件源和審核日誌。

進一步閱讀

如果您想了解有關RabbitMQ和Kafka的內部實現的更多信息,我建議您使用以下資源:

· AMQP 0.9.1模型解釋— RabbitMQ

· Apache Kafka簡介

結束語

儘管RabbitMQ和Kafka有時可以互換,但是它們的實現卻有很大的不同。 因此,我們無法將它們視為同一類工具的成員; 一個是消息代理,另一個是分佈式流平臺。

作為解決方案架構師,我們應該承認這些差異,並積極考慮在給定場景下應使用哪種類型的解決方案。 第2部分解決了這些差異,並提供了何時使用它們的指南。


(本文翻譯自Eran Stiller的文章《RabbitMQ vs. Kafka》,參考:https://medium.com/better-programming/rabbitmq-vs-kafka-1ef22a041793)


分享到:


相關文章: