【消息中間件】Redis vs Kafka vs RabbitMQ
對(duì)微服務(wù)使用異步通信時(shí),通常使用消息代理。代理確保不同微服務(wù)之間的通信可靠且穩(wěn)定,消息在系統(tǒng)內(nèi)得到管理和監(jiān)控,并且消息不會(huì)丟失。您可以從幾個(gè)消息代理中進(jìn)行選擇,它們的規(guī)模和數(shù)據(jù)功能各不相同。這篇博文將比較三種最受歡迎的代理:RabbitMQ、Kafka 和 Redis。
微服務(wù)通信:同步和異步
微服務(wù)之間有兩種常見的通信方式:同步和異步。在同步通信中,調(diào)用者在發(fā)送下一條消息之前等待響應(yīng),它作為 HTTP 之上的 REST 協(xié)議運(yùn)行。相反,在異步通信中,消息是在不等待響應(yīng)的情況下發(fā)送的。這適用于分布式系統(tǒng),通常需要消息代理來(lái)管理消息。
您選擇的通信類型應(yīng)考慮不同的參數(shù),例如您如何構(gòu)建微服務(wù)、您擁有的基礎(chǔ)設(shè)施、延遲、規(guī)模、依賴關(guān)系和通信目的。異步通信的建立可能更復(fù)雜,需要向堆棧中添加更多組件,但對(duì)微服務(wù)使用異步通信的優(yōu)點(diǎn)大于缺點(diǎn)。
異步通信優(yōu)勢(shì)
首先,異步通信根據(jù)定義是非阻塞的。它還支持比同步操作更好的擴(kuò)展。第三,在微服務(wù)崩潰的情況下,異步通信機(jī)制提供了各種恢復(fù)技術(shù),并且通常更擅長(zhǎng)處理與崩潰有關(guān)的錯(cuò)誤。此外,當(dāng)使用代理而不是 REST 協(xié)議時(shí),接收通信的服務(wù)實(shí)際上不需要相互了解。甚至可以在舊服務(wù)運(yùn)行很長(zhǎng)時(shí)間后引入新服務(wù),即更好的解耦服務(wù)。
最后,在選擇異步操作時(shí),您可以提高未來(lái)創(chuàng)建中央發(fā)現(xiàn)、監(jiān)控、負(fù)載平衡甚至策略執(zhí)行器的能力。這將為您的代碼和系統(tǒng)構(gòu)建提供靈活性、可擴(kuò)展性和更多功能。
選擇正確的消息代理
異步通信通常通過(guò)消息代理進(jìn)行管理。還有其他方法,例如 aysncio,但它們更加稀缺和有限。
在選擇代理來(lái)執(zhí)行異步操作時(shí),您應(yīng)該考慮以下幾點(diǎn):
Broker Scale — 系統(tǒng)中每秒發(fā)送的消息數(shù)。
數(shù)據(jù)持久性——恢復(fù)消息的能力。
消費(fèi)者能力——經(jīng)紀(jì)人是否能夠管理一對(duì)一和/或一對(duì)多的消費(fèi)者。
一對(duì)一
一對(duì)多
我們檢查了最新和最好的服務(wù),以找出這三個(gè)類別中最強(qiáng)大的提供商。
比較不同的消息代理
RabbitMQ (AMQP)
規(guī)模:
根據(jù)配置和資源,這里的大概是每秒 50K msg。
持久性:
支持持久性和瞬態(tài)消息。
一對(duì)一與一對(duì)多消費(fèi)者:
兩者兼而有之。
RabbitMQ 于 2007 年發(fā)布,是最早創(chuàng)建的通用消息代理之一。它是一個(gè)開源軟件,通過(guò)實(shí)現(xiàn)高級(jí)消息隊(duì)列協(xié)議 (AMQP),通過(guò)點(diǎn)對(duì)點(diǎn)和發(fā)布-訂閱方法傳遞消息。它旨在支持復(fù)雜的路由邏輯。
有一些托管服務(wù)允許您將其用作 SaaS,但它不是本地主要云提供商堆棧的一部分。RabbitMQ 支持所有主要語(yǔ)言,包括 Python、Java、.NET、PHP、Ruby、JavaScript、Go、Swift 等。
在持久模式下會(huì)出現(xiàn)一些性能問(wèn)題。
卡夫卡
規(guī)模:
每秒最多可以發(fā)送一百萬(wàn)條消息。
持久化:
是的。
一對(duì)一 vs 一對(duì)多消費(fèi)者:
只有一對(duì)多(乍一看似乎很奇怪,對(duì)吧?!)。
Kafka 由 Linkedin 于 2011 年創(chuàng)建,用于處理高吞吐量、低延遲的處理。作為分布式流媒體平臺(tái),Kafka 復(fù)制了發(fā)布訂閱服務(wù)。它提供數(shù)據(jù)持久性并存儲(chǔ)記錄流,使其能夠交換質(zhì)量消息。
Kafka 在 Azure、AWS 和 Confluent 上管理了 SaaS。他們都是Kafka項(xiàng)目的創(chuàng)造者和主要貢獻(xiàn)者。Kafka 支持所有主要語(yǔ)言,包括 Python、Java、C/C++、Clojure、.NET、PHP、Ruby、JavaScript、Go、Swift 等。
Redis
規(guī)模:
每秒最多可以發(fā)送一百萬(wàn)條消息。
持久性:
基本上,沒(méi)有——它是一個(gè)內(nèi)存中的數(shù)據(jù)存儲(chǔ)。
一對(duì)一與一對(duì)多消費(fèi)者:
兩者兼而有之。
Redis 與其他消息代理略有不同。從本質(zhì)上講,Redis 是一種內(nèi)存中數(shù)據(jù)存儲(chǔ),可用作高性能鍵值存儲(chǔ)或消息代理。另一個(gè)區(qū)別是 Redis 沒(méi)有持久性,而是將其內(nèi)存轉(zhuǎn)儲(chǔ)到磁盤/數(shù)據(jù)庫(kù)中。它也非常適合實(shí)時(shí)數(shù)據(jù)處理。
最初,Redis 不是一對(duì)一和一對(duì)多的。然而,自從 Redis 5.0 引入了 pub-sub,功能得到了提升,一對(duì)多成為了一個(gè)真正的選擇。
每個(gè)消息代理的用例
我們介紹了 RabbitMQ、Kafka 和 Redis 的一些特性。這三者都是同類中的野獸,但正如所描述的,它們的運(yùn)作方式大不相同。以下是我們針對(duì)不同用例使用的正確消息代理的建議。
短命消息:Redis
Redis 的內(nèi)存數(shù)據(jù)庫(kù)幾乎非常適合具有不需要持久性的短期消息的用例。因?yàn)樗峁O快的服務(wù)和內(nèi)存中的功能,Redis 是短保留消息的完美候選者,在這種情況下,持久性不是那么重要,您可以容忍一些損失。隨著 5.0 中 Redis 流的發(fā)布,它也是一對(duì)多用例的候選者,由于限制和舊的 pub-sub 功能,這是絕對(duì)需要的。
海量數(shù)據(jù):Kafka
Kafka 是一個(gè)高吞吐量的分布式隊(duì)列,專為長(zhǎng)時(shí)間存儲(chǔ)大量數(shù)據(jù)而構(gòu)建。Kafka 非常適合需要持久性的一對(duì)多用例。
復(fù)雜路由:RabbitMQ
RabbitMQ 是一個(gè)較舊但成熟的代理,具有許多支持復(fù)雜路由的特性和功能。當(dāng)要求的速率不高(超過(guò)幾萬(wàn)條消息/秒)時(shí),它甚至?xí)С謴?fù)雜的路由通信。
考慮您的軟件堆棧
當(dāng)然,最后要考慮的是您當(dāng)前的軟件堆棧。如果您正在尋找一個(gè)相對(duì)簡(jiǎn)單的集成過(guò)程,并且您不想在一個(gè)堆棧中維護(hù)不同的代理,您可能更傾向于使用您的堆棧已經(jīng)支持的代理。
例如,如果您在 RabbitMQ 之上的系統(tǒng)中使用 Celery for Task Queue,您將有動(dòng)力使用 RabbitMQ 或 Redis,而不是 Kafka,后者不受支持并且需要一些重寫。