新聞中心
講真,應(yīng)該選擇RabbitMQ還是Kafka?
作者:王歡 譯 2020-03-24 07:40:00
開發(fā)
架構(gòu)
開發(fā)工具
Kafka 這篇文章會先介紹一下基本的異步消息模式,然后再介紹一下 RabbitMQ 和 Kafka 以及他們的內(nèi)部結(jié)構(gòu)信息。第二部分(未完成)主要介紹這兩種技術(shù)的主要不同點(diǎn)以及他們各自的優(yōu)缺點(diǎn),最后我們會說明一下怎樣選擇這兩種技術(shù)。

為通江等地區(qū)用戶提供了全套網(wǎng)頁設(shè)計制作服務(wù),及通江網(wǎng)站建設(shè)行業(yè)解決方案。主營業(yè)務(wù)為網(wǎng)站設(shè)計、成都做網(wǎng)站、通江網(wǎng)站設(shè)計,以傳統(tǒng)方式定制建設(shè)網(wǎng)站,并提供域名空間備案等一條龍服務(wù),秉承以專業(yè)、用心的態(tài)度為用戶提供真誠的服務(wù)。我們深信只要達(dá)到每一位用戶的要求,就會得到認(rèn)可,從而選擇與我們長期合作。這樣,我們也可以走得更遠(yuǎn)!
作為一個有豐富經(jīng)驗(yàn)的微服務(wù)系統(tǒng)架構(gòu)師,經(jīng)常有人問我,應(yīng)該選擇 RabbitMQ 還是 Kafka?
[[319666]]
圖片來自 Pexels
基于某些原因, 許多開發(fā)者會把這兩種技術(shù)當(dāng)做等價的來看待。的確,在一些案例場景下選擇 RabbitMQ 還是 Kafka 沒什么差別,但是這兩種技術(shù)在底層實(shí)現(xiàn)方面是有許多差異的。
不同的場景需要不同的解決方案,選錯一個方案能夠嚴(yán)重的影響你對軟件的設(shè)計,開發(fā)和維護(hù)的能力。
這篇文章會先介紹一下基本的異步消息模式,然后再介紹一下 RabbitMQ 和 Kafka 以及他們的內(nèi)部結(jié)構(gòu)信息。第二部分(未完成)主要介紹這兩種技術(shù)的主要不同點(diǎn)以及他們各自的優(yōu)缺點(diǎn),最后我們會說明一下怎樣選擇這兩種技術(shù)。
異步消息模式
異步消息可以作為解耦消息的生產(chǎn)和處理的一種解決方案。提到消息系統(tǒng),我們通常會想到兩種主要的消息模式——消息隊列和發(fā)布/訂閱模式。
消息隊列
利用消息隊列可以解耦生產(chǎn)者和消費(fèi)者。多個生產(chǎn)者可以向同一個消息隊列發(fā)送消息。
但是,一個消息在被一個消息者處理的時候,這個消息在隊列上會被鎖住或者被移除并且其他消費(fèi)者無法處理該消息。也就是說一個具體的消息只能由一個消費(fèi)者消費(fèi)。
消息隊列
需要額外注意的是,如果消費(fèi)者處理一個消息失敗了,消息系統(tǒng)一般會把這個消息放回隊列,這樣其他消費(fèi)者可以繼續(xù)處理。
消息隊列除了提供解耦功能之外,它還能夠?qū)ιa(chǎn)者和消費(fèi)者進(jìn)行獨(dú)立的伸縮(scale),以及提供對錯誤處理的容錯能力。
發(fā)布/訂閱
發(fā)布/訂閱(pub/sub)模式中,單個消息可以被多個訂閱者并發(fā)的獲取和處理。
發(fā)布/訂閱
例如,一個系統(tǒng)中產(chǎn)生的事件可以通過這種模式讓發(fā)布者通知所有訂閱者。在許多隊列系統(tǒng)中常常用主題(topics)這個術(shù)語指代發(fā)布/訂閱模式。
在 RabbitMQ 中,主題就是發(fā)布/訂閱模式的一種具體實(shí)現(xiàn)(更準(zhǔn)確點(diǎn)說是交換器(exchange)的一種),但是在這篇文章中,我會把主題和發(fā)布/訂閱當(dāng)做等價來看待。
一般來說,訂閱有兩種類型:
- 臨時(ephemeral)訂閱,這種訂閱只有在消費(fèi)者啟動并且運(yùn)行的時候才存在。一旦消費(fèi)者退出,相應(yīng)的訂閱以及尚未處理的消息就會丟失。
- 持久(durable)訂閱,這種訂閱會一直存在,除非主動去刪除。消費(fèi)者退出后,消息系統(tǒng)會繼續(xù)維護(hù)該訂閱,并且后續(xù)消息可以被繼續(xù)處理。
RabbitMQ
RabbitMQ 作為消息中間件的一種實(shí)現(xiàn),常常被當(dāng)作一種服務(wù)總線來使用。RabbitMQ 原生就支持上面提到的兩種消息模式。
其他一些流行的消息中間件的實(shí)現(xiàn)有 ActiveMQ,ZeroMQ,Azure Service Bus 以及 Amazon Simple Queue Service(SQS)。
這些消息中間件的實(shí)現(xiàn)有許多共通的地方;這邊文章中提到的許多概念大部分都適用于這些中間件。
隊列
RabbitMQ 支持典型的開箱即用的消息隊列。開發(fā)者可以定義一個命名隊列,然后發(fā)布者可以向這個命名隊列中發(fā)送消息。最后消費(fèi)者可以通過這個命名隊列獲取待處理的消息。
消息交換器
RabbitMQ 使用消息交換器來實(shí)現(xiàn)發(fā)布/訂閱模式。發(fā)布者可以把消息發(fā)布到消息交換器上而不用知道這些消息都有哪些訂閱者。
每一個訂閱了交換器的消費(fèi)者都會創(chuàng)建一個隊列;然后消息交換器會把生產(chǎn)的消息放入隊列以供消費(fèi)者消費(fèi)。消息交換器也可以基于各種路由規(guī)則為一些訂閱者過濾消息。
RabbitMQ 消息交換器
需要重點(diǎn)注意的是 RabbitMQ 支持臨時和持久兩種訂閱類型。消費(fèi)者可以調(diào)用 RabbitMQ 的 API 來選擇他們想要的訂閱類型。
根據(jù) RabbitMQ 的架構(gòu)設(shè)計,我們也可以創(chuàng)建一種混合方法——訂閱者以組隊的方式然后在組內(nèi)以競爭關(guān)系作為消費(fèi)者去處理某個具體隊列上的消息,這種由訂閱者構(gòu)成的組我們稱為消費(fèi)者組。
按照這種方式,我們實(shí)現(xiàn)了發(fā)布/訂閱模式,同時也能夠很好的伸縮(scale-up)訂閱者去處理收到的消息。
發(fā)布/訂閱與隊列的聯(lián)合使用
Apache Kafka
Apache Kafka 不是消息中間件的一種實(shí)現(xiàn)。相反,它只是一種分布式流式系統(tǒng)。
不同于基于隊列和交換器的 RabbitMQ,Kafka 的存儲層是使用分區(qū)事務(wù)日志來實(shí)現(xiàn)的。
Kafka 也提供流式 API 用于實(shí)時的流處理以及連接器 API 用來更容易的和各種數(shù)據(jù)源集成;當(dāng)然,這些已經(jīng)超出了本篇文章的討論范圍。
云廠商為 Kafka 存儲層提供了可選的方案,比如 Azure Event Hubsy 以及 AWS Kinesis Data Streams 等。
對于 Kafka 流式處理能力,還有一些特定的云方案和開源方案,不過,話說回來,它們也超出了本篇的范圍。
主題
Kafka 沒有實(shí)現(xiàn)隊列這種東西。相應(yīng)的,Kafka 按照類別存儲記錄集,并且把這種類別稱為主題。
Kafka 為每個主題維護(hù)一個消息分區(qū)日志。每個分區(qū)都是由有序的不可變的記錄序列組成,并且消息都是連續(xù)的被追加在尾部。
當(dāng)消息到達(dá)時,Kafka 就會把他們追加到分區(qū)尾部。默認(rèn)情況下,Kafka 使用輪詢分區(qū)器(partitioner)把消息一致的分配到多個分區(qū)上。
Kafka 可以改變創(chuàng)建消息邏輯流的行為。例如,在一個多租戶的應(yīng)用中,我們可以根據(jù)每個消息中的租戶 ID 創(chuàng)建消息流。
IoT 場景中,我們可以在常數(shù)級別下根據(jù)生產(chǎn)者的身份信息(identity)將其映射到一個具體的分區(qū)上。
確保來自相同邏輯流上的消息映射到相同分區(qū)上,這就保證了消息能夠按照順序提供給消費(fèi)者。
Kafka 生產(chǎn)者
消費(fèi)者通過維護(hù)分區(qū)的偏移(或者說索引)來順序的讀出消息,然后消費(fèi)消息。
單個消費(fèi)者可以消費(fèi)多個不同的主題,并且消費(fèi)者的數(shù)量可以伸縮到可獲取的最大分區(qū)數(shù)量。
所以在創(chuàng)建主題的時候,我們要認(rèn)真的考慮一下在創(chuàng)建的主題上預(yù)期的消息吞吐量。消費(fèi)同一個主題的多個消費(fèi)者構(gòu)成的組稱為消費(fèi)者組。
通過 Kafka 提供的 API 可以處理同一消費(fèi)者組中多個消費(fèi)者之間的分區(qū)平衡以及消費(fèi)者當(dāng)前分區(qū)偏移的存儲。
Kafka 消費(fèi)者
Kafka 實(shí)現(xiàn)的消息模式
Kafka 的實(shí)現(xiàn)很好地契合發(fā)布/訂閱模式。生產(chǎn)者可以向一個具體的主題發(fā)送消息,然后多個消費(fèi)者組可以消費(fèi)相同的消息。每一個消費(fèi)者組都可以獨(dú)立的伸縮去處理相應(yīng)的負(fù)載。
由于消費(fèi)者維護(hù)自己的分區(qū)偏移,所以他們可以選擇持久訂閱或者臨時訂閱,持久訂閱在重啟之后不會丟失偏移而臨時訂閱在重啟之后會丟失偏移并且每次重啟之后都會從分區(qū)中最新的記錄開始讀取。
但是這種實(shí)現(xiàn)方案不能完全等價的當(dāng)做典型的消息隊列模式看待。當(dāng)然,我們可以創(chuàng)建一個主題,這個主題和擁有一個消費(fèi)者的消費(fèi)組進(jìn)行關(guān)聯(lián)。
這樣我們就模擬出了一個典型的消息隊列。不過這會有許多缺點(diǎn),我們會在第二部分詳細(xì)討論。
值得特別注意的是,Kafka 是按照預(yù)先配置好的時間保留分區(qū)中的消息,而不是根據(jù)消費(fèi)者是否消費(fèi)了這些消息。
這種保留機(jī)制可以讓消費(fèi)者自由的重讀之前的消息。另外,開發(fā)者也可以利用Kafka的存儲層來實(shí)現(xiàn)諸如事件溯源和日志審計功能。
結(jié)束語
盡管有時候 RabbitMQ 和 Kafka 可以當(dāng)做等價來看,但是他們的實(shí)現(xiàn)是非常不同的。
所以我們不能把他們當(dāng)做同種類的工具來看待;一個是消息中間件,另一個是分布式流式系統(tǒng)。
作為解決方案架構(gòu)師,我們要能夠認(rèn)識到它們之間的差異并且盡可能的考慮在給定場景中使用哪種類型的解決方案。
第二部分(未完成)會指出這些差異并且提供什么時候使用哪種方案的指導(dǎo)建議,后面會為大家更新。
文章標(biāo)題:講真,應(yīng)該選擇RabbitMQ還是Kafka?
文章來源:http://fisionsoft.com.cn/article/cdiidch.html


咨詢
建站咨詢
