消息中間件Kafka與RabbitMQ誰更勝一籌?

在 IM 這種講究高併發、高消息吞吐的互聯網場景下,MQ 消息中間件是個很重要的基礎設施,它在 IM 系統的服務端架構中擔當消息中轉、消息削峯、消息交換異步化等角色。
當然,MQ 消息中間件的作用遠不止於此,它的價值不僅僅存在於技術上,更重要的是改變了以往同步處理消息的思路。
比如進行 IM 消息歷史存儲時,傳統的信息系統作法可能是收到一條消息就馬上同步存入數據庫,這種作法在小併發量的情況下可以很好的工作,但互聯網大併發環境下就是災難。
消息中間件Kafka與RabbitMQ誰更勝一籌?
MQ 消息中間件可以理解爲一個水池,水池的這頭是消息生產者,水池的那頭是消息消費者,生產者和消息者無需直接對接,這將帶來很多好處:業務解耦、架構分佈式化等,生產者和消費者互相完全透明。
但市面上的 MQ 消息中間件產品很多,作爲 IM 系統中必不可少的一環,我們該如何選型?
什麼是消息隊列中間件
消息隊列中間件(簡稱消息中間件)是指利用高效可靠的消息傳遞機制進行與平臺無關的數據交流,並基於數據通信來進行分佈式系統的集成。
通過提供消息傳遞和消息排隊模型,它可以在分佈式環境下提供應用解耦、彈性伸縮、冗餘存儲、流量削峯、異步通信、數據同步等等功能,其作爲分佈式系統架構中的一個重要組件,有着舉足輕重的地位。
消息中間件Kafka與RabbitMQ誰更勝一籌?
目前開源的消息中間件可謂是琳琅滿目,能讓大家耳熟能詳的就有很多,比如 ActiveMQ、RabbitMQ、Kafka、RocketMQ、ZeroMQ 等,不管選擇其中的哪一款,都會有用的不趁手的地方,畢竟不是爲你量身定製的。
可能有些大廠在長期的使用過程中積累了一定的經驗,加上其消息隊列的使用場景也相對穩定固化,或者目前市面上的消息中間件無法滿足自身需求,同時它也具備足夠的精力和人力而選擇自研來爲自己量身打造一款消息中間件。
但是絕大多數公司還是不會選擇重複造輪子,那麼選擇一款適合自己的消息中間件顯得尤爲重要。
就算是前者,那麼在自研出穩定且可靠的相關產品之前也會經歷這樣一個選型過程。
在整體架構中引入消息中間件,勢必要考慮很多因素,比如成本及收益問題,怎麼樣才能達到最優的性價比?
雖然消息中間件種類繁多,但是各自都有各自的側重點,選擇合適自己、揚長避短無疑是最好的方式。如果你對此感到無所適從,本文或許可以參考一二。
各類消息隊列簡述
ActiveMQ
Apache 出品的、採用 Java 語言編寫的完全基於 JMS1.1 規範的面向消息的中間件,爲應用程序提供高效的、可擴展的、穩定的和安全的企業級消息通信。
不過由於歷史原因包袱太重,目前市場份額沒有後面三種消息中間件多,其最新架構被命名爲 Apollo,號稱下一代 ActiveMQ,有興趣的同學可自行了解。
RabbitMQ
採用 Erlang 語言實現的 AMQP 協議的消息中間件,最初起源於金融系統,用於在分佈式系統中存儲轉發消息。
RabbitMQ 發展到今天,被越來越多的人認可,這和它在可靠性、可用性、擴展性、功能豐富等方面的卓越表現是分不開的。
Kafka
起初是由 LinkedIn 公司採用 Scala 語言開發的一個分佈式、多分區、多副本且基於 ZooKeeper 協調的分佈式消息系統,現已捐獻給 Apache 基金會。
它是一種高吞吐量的分佈式發佈訂閱消息系統,以可水平擴展和高吞吐率而被廣泛使用。目前越來越多的開源分佈式處理系統如 Cloudera、Apache Storm、Spark、Flink 等都支持與 Kafka 集成。
RocketMQ
是阿里開源的消息中間件,目前已經捐獻給 Apache 基金會,它是由 Java 語言開發的,具備高吞吐量、高可用性、適合大規模分佈式系統應用等特點,經歷過雙 11 的洗禮,實力不容小覷。
ZeroMQ
號稱史上最快的消息隊列,基於 C 語言開發。ZeroMQ 是一個消息處理隊列庫,可在多線程、多內核和主機之間彈性伸縮。
雖然大多數時候我們習慣將其歸入消息隊列家族之中,但是其和前面的幾款有着本質的區別,ZeroMQ 本身就不是一個消息隊列服務器,更像是一組底層網絡通訊庫,對原有的 Socket API 上加上一層封裝而已。
目前市面上的消息中間件還有很多,比如騰訊系的 PhxQueue、CMQ、CKafka,又比如基於 Go 語言的 NSQ,有時人們也把類似 Redis 的產品也看做消息中間件的一種。
當然,它們都很優秀,但是本文篇幅限制無法窮其所有,下面會針對性地挑選 RabbitMQ 和 Kafka 兩款典型的消息中間件來做分析,力求站在一個公平公正的立場來闡述消息中間件選型中的各個要點。
消息中間件選型要點
衡量一款消息中間件是否符合需求,需要從多個維度進行考察。
首要的就是功能維度,這個直接決定了你能否最大程度上地實現開箱即用,進而縮短項目週期、降低成本等。
如果一款消息中間件的功能達不到想要的功能,那麼就需要進行二次開發,這樣會增加項目的技術難度、複雜度以及增大項目週期等。
消息中間件具體選型指標
功能維度
功能維度又可以劃分成多個子維度,大致可以分爲以下這些。
優先級隊列
優先級隊列不同於先進先出隊列,優先級高的消息具備優先被消費的特權,這樣可以爲下游提供不同消息級別的保證。
不過這個優先級也是需要有一個前提的:如果消費者的消費速度大於生產者的速度,並且消息中間件服務器(一般簡單的稱之爲 Broker)中沒有消息堆積。
那麼對於發送的消息設置優先級也就沒有什麼實質性的意義了,因爲生產者剛發送完一條消息就被消費者消費了,那麼就相當於 Broker 中至多隻有一條消息,對於單條消息來說優先級是沒有什麼意義的。
延遲隊列
當你在網上購物的時候是否會遇到這樣的提示:“三十分鐘之內未付款,訂單自動取消”,這個是延遲隊列的一種典型應用場景。
延遲隊列存儲的是對應的延遲消息,所謂“延遲消息”是指當消息被髮送以後,並不想讓消費者立刻拿到消息,而是等待特定時間後,消費者才能拿到這個消息進行消費。
延遲隊列一般分爲兩種:
基於消息的延遲,是指爲每條消息設置不同的延遲時間,那麼每當隊列中有新消息進入的時候就會重新根據延遲時間排序,當然這也會對性能造成極大的影響。
基於隊列的延遲,實際應用中大多采用這種,設置不同延遲級別的隊列,比如5s、10s、30s、1min、5mins、10mins等,每個隊列中消息的延遲時間都是相同的,這樣免去了延遲排序所要承受的性能之苦,通過一定的掃描策略(比如定時)即可投遞超時的消息。
死信隊列
由於某些原因消息無法被正確投遞,爲了確保消息不會被無故丟棄,一般將其置於一個特殊角色的隊列,這個隊列稱爲死信隊列。
與此對應的還有一個“回退隊列”的概念,試想如果消費者在消費時發生了異常,那麼就不會對這一次消費進行確認(Ack), 進而發生回滾消息的操作之後消息始終會放在隊列的頂部,然後不斷被處理和回滾,導致隊列陷入死循環。
爲了解決這個問題,可以爲每個隊列設置一個回退隊列,它和死信隊列都是爲異常的處理提供的一種機制保障。實際情況下,回退隊列的角色可以由死信隊列和重試隊列來扮演。
重試隊列
其實可以看成是一種回退隊列,具體指消費端消費消息失敗時,爲防止消息無故丟失而重新將消息回滾到 Broker 中。
與回退隊列不同的是重試隊列一般分成多個重試等級,每個重試等級一般也會設置重新投遞延時,重試次數越多投遞延時就越大。
舉個例子:消息第一次消費失敗入重試隊列 Q1,Q1 的重新投遞延遲爲 5s,在 5s 過後重新投遞該消息。
如果消息再次消費失敗則入重試隊列 Q2,Q2 的重新投遞延遲爲 10s,在 10s 過後再次投遞該消息。
以此類推,重試越多次重新投遞的時間就越久,爲此需要設置一個上限,超過投遞次數就入死信隊列。
重試隊列與延遲隊列有相同的地方,都是需要設置延遲級別,它們彼此的區別是:延遲隊列動作由內部觸發,重試隊列動作由外部消費端觸發;延遲隊列作用一次,而重試隊列的作用範圍會向後傳遞。
消費模式
消費模式分爲推(push)模式和拉(pull)模式:
推模式,是指由 Broker 主動推送消息至消費端,實時性較好,不過需要一定的流制機制來確保服務端推送過來的消息不會壓垮消費端。
拉模式,是指消費端主動向 Broker 端請求拉取(一般是定時或者定量)消息,實時性較推模式差,但是可以根據自身的處理能力而控制拉取的消息量。
廣播消費
消息一般有兩種傳遞模式——點對點(P2P,Point-to-Point)模式和發佈/訂閱(Pub/Sub)模式:
對於點對點的模式而言,消息被消費以後,隊列中不會再存儲,所以消息消費者不可能消費到已經被消費的消息。雖然隊列可以支持多個消費者,但是一條消息只會被一個消費者消費。
發佈訂閱模式定義瞭如何向一個內容節點發布和訂閱消息,這個內容節點稱爲主題(Topic),主題可以認爲是消息傳遞的中介,消息發佈者將消息發佈到某個主題,而消息訂閱者則從主題中訂閱消息。
主題使得消息的訂閱者與消息的發佈者互相保持獨立,不需要進行接觸即可保證消息的傳遞,發佈/訂閱模式在消息的一對多廣播時採用。
RabbitMQ 是一種典型的點對點模式,而 Kafka 是一種典型的發佈訂閱模式。
但是 RabbitMQ 中可以通過設置交換器類型來實現發佈訂閱模式而達到廣播消費的效果,Kafka 中也能以點對點的形式消費,你完全可以把其消費組(Consumer Group)的概念看成是隊列的概念。
不過對比來說,Kafka 中因爲有了消息回溯功能的存在,對於廣播消費的力度支持比 RabbitMQ 的要強。
消息回溯
一般消息在消費完成之後就被處理了,之後再也不能消費到該條消息。消息回溯正好相反,是指消息在消費完成之後,還能消費到之前被消費掉的消息。
對於消息而言,經常面臨的問題是“消息丟失”,至於是真正由於消息中間件的缺陷丟失還是由於使用方的誤用而丟失,一般很難追查。
如果消息中間件本身具備消息回溯功能的話,可以通過回溯消費復現“丟失的”消息進而查出問題的源頭所在。
消息回溯的作用遠不止於此,比如還有索引恢復、本地緩存重建,有些業務補償方案也可以採用回溯的方式來實現。
消息堆積+持久化
流量削峯是消息中間件的一個非常重要的功能,而這個功能其實得益於其消息堆積能力。
從某種意義上來講,如果一個消息中間件不具備消息堆積的能力,那麼就不能把它看做是一個合格的消息中間件。
消息堆積分內存式堆積和磁盤式堆積:
RabbitMQ 是典型的內存式堆積,但這並非絕對,在某些條件觸發後會有換頁動作來將內存中的消息換頁到磁盤(換頁動作會影響吞吐),或者直接使用惰性隊列來將消息直接持久化至磁盤中。
Kafka 是一種典型的磁盤式堆積,所有的消息都存儲在磁盤中。
一般來說,磁盤的容量會比內存的容量要大得多,對於磁盤式的堆積其堆積能力就是整個磁盤的大小。
從另外一個角度講,消息堆積也爲消息中間件提供了冗餘存儲的功能。援引《紐約時報》的案例,其直接將 Kafka 用作存儲系統。
消息追蹤
對於分佈式架構系統中的鏈路追蹤(Trace),大家一定不陌生。對於消息中間件,消息的鏈路追蹤(以下簡稱消息追蹤)同樣重要,最通俗來理解,就是要知道消息從哪來,存在哪裏以及發往哪裏去。
基於此功能,我們可以對發送或者消費完的消息進行鏈路追蹤服務,進而可以進行問題的快速定位與排查。
消息過濾
消息過濾是指按照既定的過濾規則爲下游用戶提供指定類別的消息。
就以 Kafka 而言,完全可以將不同類別的消息發送至不同的 Topic 中,由此可以實現某種意義的消息過濾,或者 Kafka 還可以根據分區對同一個 Topic 中的消息進行分類。
不過,更加嚴格意義上的消息過濾,應該是對既定的消息採取一定的方式按照一定的過濾規則進行過濾。
同樣以 Kafka 爲例,可以通過客戶端提供的 Consumer Interceptor 接口或者 Kafka Stream 的 Filter 功能進行消息過濾。
多租戶
也可以稱爲多重租賃技術,是一種軟件架構技術,主要用來實現多用戶的環境下公用相同的系統或程序組件,並且仍可以確保各用戶間數據的隔離性。
RabbitMQ 就能夠支持多租戶技術,每一個租戶表示爲一個 VHost,其本質上是一個獨立的小型 RabbitMQ 服務器,又有自己獨立的隊列、交換器及綁定關係等,並且它擁有自己獨立的權限。
VHost 就像是物理機中的虛擬機一樣,它們在各個實例間提供邏輯上的分離,爲不同程序安全保密地允許數據,它既能將同一個 RabbitMQ 中的衆多客戶區分開,又可以避免隊列和交換器等命名衝突。
多協議支持
消息是信息的載體,爲了讓生產者和消費者都能理解所承載的信息(生產者需要知道如何構造消息,消費者需要知道如何解析消息),它們就需要按照一種統一的格式描述消息,這種統一的格式稱之爲消息協議。
有效的消息一定具有某種格式,而沒有格式的消息是沒有意義的。
一般消息層面的協議有 AMQP、MQTT、STOMP、XMPP 等(消息領域中的 JMS 更多的是一個規範而不是一個協議),支持的協議越多其應用範圍就會越廣,通用性越強。
比如 RabbitMQ 能夠支持 MQTT 協議就讓其在物聯網應用中獲得一席之地。還有的消息中間件是基於其本身的私有協議運轉的,典型的如 Kafka。
跨語言支持
對很多公司而言,其技術棧體系中會有多種編程語言,如 C/C++、Java、Go、PHP 等,消息中間件本身具備應用解耦的特性,如果能夠進一步的支持多客戶端語言,那麼就可以將此特性的效能擴大。
跨語言的支持力度也從側面反映出一個消息中間件的流行程度。
流量控制
針對的是發送方和接收方速度不匹配的問題,提供一種速度匹配服務抑制發送速率使接收方應用程序的讀取速率與之相適應。通常的流控方法有 Stop-and-Wait、滑動窗口以及令牌桶等。
消息順序性
顧名思義,是指保證消息有序。這個功能有個很常見的應用場景就是 CDC(Change Data Chapture)。
以 MySQL 爲例,如果其傳輸的 Binlog 的順序出錯,比如原本是先對一條數據加 1,然後再乘以 2,發送錯序之後就變成了先乘以 2 後加 1,造成數據不一致。
安全機制
在 Kafka 0.9 版本之後就開始增加了身份認證和權限控制兩種安全機制:
身份認證,是指客戶端與服務端連接進行身份認證,包括客戶端與 Broker 之間、Broker 與 Broker 之間、Broker 與 ZooKeeper 之間的連接認證,目前支持 SSL、SASL 等認證機制。
權限控制,是指對客戶端的讀寫操作進行權限控制,包括對消息或 Kafka 集羣操作權限控制。權限控制是可插拔的,並支持與外部的授權服務進行集成。
對於 RabbitMQ 而言,其同樣提供身份認證(TLS/SSL、SASL)和權限控制(讀寫操作)的安全機制。
消息冪等性
確保消息在生產者和消費者之間進行傳輸,一般有三種傳輸保障(Delivery Guarantee):
At most once,至多一次,消息可能丟失,但絕不會重複傳輸。
At least once,至少一次,消息絕不會丟,但是可能會重複。
Exactly once,精確一次,每條消息肯定會被傳輸一次且僅一次。
對於大多數消息中間件而言,一般只提供 At most once 和 At least once 兩種傳輸保障,對於第三種一般很難做到,由此消息冪等性也很難保證。
Kafka 自 0.11 版本開始引入了冪等性和事務,Kafka 的冪等性是指單個生產者對於單分區單會話的冪等。
而事務可以保證原子性地寫入到多個分區,即寫入到多個分區的消息要麼全部成功,要麼全部回滾,這兩個功能加起來可以讓 Kafka 具備 EOS(Exactly Once Semantic)的能力。
不過如果要考慮全局的冪等,還需要從上下游方面綜合考慮,即關聯業務層面,冪等處理本身也是業務層面所需要考慮的重要議題。
以下游消費者層面爲例,有可能消費者消費完一條消息之後沒有來得及確認消息就發生異常,等到恢復之後又得重新消費原來消費過的那條消息,那麼這種類型的消息冪等是無法由消息中間件層面來保證的。
如果要保證全局的冪等,需要引入更多的外部資源來保證,比如以訂單號作爲唯一性標識,並且在下游設置一個去重表。
事務性消息
事務本身是一個並不陌生的詞彙,事務是由事務開始(Begin Transaction)和事務結束(End Transaction)之間執行的全體操作組成。
支持事務的消息中間件並不在少數,Kafka 和 RabbitMQ 都支持,不過此兩者的事務是指生產者發生消息的事務,要麼發送成功,要麼發送失敗。
消息中間件可以作爲用來實現分佈式事務的一種手段,但其本身並不提供全局分佈式事務的功能。
下表是對 Kafka 與 RabbitMQ 功能的總結性對比及補充說明:
消息中間件Kafka與RabbitMQ誰更勝一籌?
性能
功能維度是消息中間件選型中的一個重要的參考維度,但這並不是唯一的維度,有時候性能比功能還要重要,況且性能和功能很多時候是相悖的,魚和熊掌不可兼得。
Kafka 在開啓冪等、事務功能的時候會使其性能降低;RabbitMQ 在開啓 rabbitmq_tracing 插件的時候也會極大影響其性能。
性能指什麼?
消息中間件的性能一般是指其吞吐量。雖然從功能維度上來說,RabbitMQ 的優勢要大於 Kafka,但是 Kafka 的吞吐量要比 RabbitMQ 高出 1 至 2 個數量級。
一般 RabbitMQ 的單機 QPS 在萬級別之內,而 Kafka 的單機 QPS 可以維持在十萬級別,甚至可以達到百萬級。
註明:消息中間件的吞吐量始終會受到硬件層面的限制。就以網卡帶寬爲例,如果單機單網卡的帶寬爲 1Gbps,如果要達到百萬級的吞吐,那麼消息體大小不得超過(1Gb/8)/100W,即約等於 134B。
換句話說如果消息體大小超過 134B,那麼就不可能達到百萬級別的吞吐。這種計算方式同樣可以適用於內存和磁盤。
性能的指標是什麼?
時延作爲性能維度的一個重要指標,卻往往在消息中間件領域被忽視,因爲一般使用消息中間件的場景對時效性的要求並不是很高,如果要求時效性完全可以採用 RPC 的方式實現。
消息中間件具備消息堆積的能力,消息堆積越大也就意味着端到端的時延也就越長,與此同時延時隊列也是某些消息中間件的一大特色。那麼爲什麼還要關注消息中間件的時延問題呢?
消息中間件能夠解耦系統,對於一個時延較低的消息中間件而言,它可以讓上游生產者發送消息之後可以迅速的返回,也可以讓消費者更加快速的獲取到消息,在沒有堆積的情況下,可以讓整體上下游的應用之間的級聯動作更加高效。
雖然不建議在時效性很高的場景下使用消息中間件,但是如果所使用的消息中間件的時延方面比較優秀,那麼對於整體系統的性能將會是一個不小的提升。
可靠性+可用性
消息丟失是使用消息中間件時所不得不面對的一個痛點,其背後消息可靠性也是衡量消息中間件好壞的一個關鍵因素。尤其是在金融支付領域,消息可靠性尤爲重要。
然而說到可靠性必然要說到可用性,注意這兩者之間的區別:
消息中間件的可靠性是指對消息不丟失的保障程度。
而消息中間件的可用性是指無故障運行的時間百分比,通常用幾個 9 來衡量。
從狹義的角度來說,分佈式系統架構是一致性協議理論的應用實現,對於消息可靠性和可用性而言也可以追溯到消息中間件背後的一致性協議:
對於 Kafka 而言,其採用的是類似 PacificA 的一致性協議,通過 ISR(In-Sync-Replica)來保證多副本之間的同步,並且支持強一致性語義(通過 Acks 實現)。
對應的 RabbitMQ 是通過鏡像環形隊列實現多副本及強一致性語義的。
多副本可以保證在 Master 節點宕機異常之後可以提升 Slave 作爲新的 Master 而繼續提供服務來保障可用性。
Kafka 設計之初是爲日誌處理而生,給人們留下了數據可靠性要求不高的不良印象,但是隨着版本的升級優化,其可靠性得到極大的增強,詳細可以參考 KIP101。
就目前而言,在金融支付領域使用 RabbitMQ 居多,而在日誌處理、大數據等方面 Kafka 使用居多,隨着 RabbitMQ 性能的不斷提升和 Kafka 可靠性的進一步增強,相信彼此都能在以前不擅長的領域分得一杯羹。
同步刷盤是增強一個組件可靠性的有效方式,消息中間件也不例外,Kafka 和 RabbitMQ 都可以支持同步刷盤。
但是筆者對同步刷盤有一定的疑問:絕大多數情景下,一個組件的可靠性不應該由同步刷盤這種極其損耗性能的操作來保障,而是採用多副本的機制來保證。
這裏還要提及的一個方面是擴展能力,這裏我狹隘地將此歸納到可用性這一維度,消息中間件的擴展能力能夠增強其可用能力及範圍,比如前面提到的 RabbitMQ 支持多種消息協議,這個就是基於其插件化的擴展實現。
還有從集羣部署上來講,歸功於 Kafka 的水平擴展能力,其基本上可以達到線性容量提升的水平,在 LinkedIn 實踐介紹中就提及了有部署超過千臺設備的 Kafka 集羣。
運維管理
在消息中間件的使用過程中難免會出現各式各樣的異常情況,有客戶端的,也有服務端的,那麼怎樣及時有效的進行監測及修復?
業務線流量有峯值有低谷,尤其是電商領域,那麼怎樣進行有效的容量評估,尤其是大促期間?腳踢電源、網線被挖等事件層出不窮,如何有效的做好異地多活?
這些都離不開消息中間件的衍生產品——運維管理。運維管理也可以進行進一步的細分,比如申請、審覈、監控、告警、管理、容災、部署等。
申請、審覈很好理解,在源頭對資源進行管控,既可以有效校正應用方的使用規範,配合監控也可以做好流量統計與流量評估工作。
一般申請、審覈與公司內部系統交融性較大,不適合使用開源類的產品。
監控、告警也比較好理解,對消息中間件的使用進行全方位的監控,既可以爲系統提供基準數據,也可以在檢測到異常的情況配合告警,以便運維、開發人員的迅速介入。
除了一般的監控項(比如硬件、GC 等)之外,消息中間件還需要關注端到端時延、消息審計、消息堆積等方面:
對於 RabbitMQ 而言,最正統的監控管理工具莫過於 rabbitmq_management 插件了,但是社區內還有 AppDynamics、Collectd、DataDog、Ganglia、Munin、Nagios、New Relic、Prometheus、Zenoss 等多種優秀的產品。
Kafka 在此方面也毫不遜色,比如:Kafka Manager、Kafka Monitor、Kafka Offset Monitor、Burrow、Chaperone、Confluent Control Center 等產品,尤其是 Cruise 還可以提供自動化運維的功能。
不管是擴容、降級、版本升級、集羣節點部署、還是故障處理都離不開管理工具的應用,一個配套完備的管理工具集可以在遇到變更時做到事半功倍。
故障可大可小,一般是一些應用異常,也可以是機器掉電、網絡異常、磁盤損壞等單機故障,這些故障單機房內的多副本足以應付。
如果是機房故障就要涉及異地容災了,關鍵點在於如何有效的進行數據複製,Kafka 可以參考 MirrorMarker、uReplicator 等產品,而 RabbitMQ 可以參考 Federation 和 Shovel。
社區力度及生態發展
對於目前流行的編程語言而言,如 Java、Python,如果你在使用過程中遇到了一些異常,基本上可以通過搜索引擎的幫助來得到解決,因爲一個產品用的人越多,踩過的坑也就越多,對應的解決方案也就越多。
消息中間件也同樣適用,如果你選擇了一種“生僻”的消息中間件,可能在某些方面運用的得心應手,但是版本更新緩慢、遇到棘手問題也難以得到社區的支持而越陷越深。
相反如果你選擇了一種“流行”的消息中間件,其更新力度大,不僅可以迅速的彌補之前的不足,而且也能順應技術的快速發展來變更一些新的功能,這樣可以讓你也“站在巨人的肩膀上”。
在運維管理維度我們提及了 Kafka 和 RabbitMQ 都有一系列開源的監控管理產品,這些正是得益於其社區及生態的迅猛發展。
消息中間件選型誤區總結
選型誤區
在進行消息中間件選型之前可以先問自己一個問題:是否真的需要一個消息中間件?
在搞清楚這個問題之後,還可以繼續問自己一個問題:是否需要自己維護一套消息中間件?
很多初創型公司爲了節省成本會選擇直接購買消息中間件有關的雲服務,自己只需要關注收發消息即可,其餘的都可以外包出去。
很多人面對消息中間件有一種自研的衝動,你完全可以對 Java 中的 ArrayBlockingQueue 做一個簡單的封裝,你也可以基於文件、數據庫、Redis 等底層存儲封裝而形成一個消息中間件。
消息中間件做爲一個基礎組件並沒有想象中的那麼簡單,其背後還需要配套的管理運維整個生態的產品集。
自研還會有交接問題,如果文檔不齊全、運作不規範將會帶給新人噩夢般的體驗。
是否真的有自研的必要?如果不是 KPI 的壓迫可以先考慮下面這兩個問題:
目前市面上的消息中間件是否都真的無法滿足目前的業務需求?
團隊是否有足夠的能力、人力、財力、精力來支持自研?
很多人在做消息中間件選型時會參考網絡上的很多對比類的文章,但是其專業性、嚴謹性、以及其政治立場問題都有待考證,需要帶着懷疑的態度去審視這些文章。
比如有些文章會在沒有任何限定條件及場景的情況下直接定義某款消息中間件最好。
還有些文章沒有指明消息中間件版本及測試環境就來做功能和性能對比分析,諸如此類的文章都可以唾棄之。
消息中間件猶如小馬過河,選擇合適的才最重要。這需要貼合自身的業務需求,技術服務於業務,大體上可以根據上一節所提及的功能、性能等 6 個維度來一一進行篩選。更深層次的抉擇在於你能否掌握其魂。
筆者鄙見:RabbitMQ 在於 Routing,而 Kafka 在於 Streaming,瞭解其根本對於自己能夠對症下藥選擇到合適的消息中間件尤爲重要。
消息中間件選型切忌一味的追求性能或者功能,性能可以優化,功能可以二次開發。
如果要在功能和性能方面做一個抉擇的話,那麼首選性能,因爲總體上來說性能優化的空間沒有功能擴展的空間大。然而看長期發展,生態又比性能以及功能都要重要。
可靠性誤區
很多時候,可靠性方面也容易存在一個誤區:想要找到一個產品來保證消息的絕對可靠,很不幸的是這世界上沒有絕對的東西,只能說盡量趨於完美。
想要儘可能的保障消息的可靠性也並非單單隻靠消息中間件本身,還要依賴於上下游,需要從生產端、服務端和消費端這 3 個維度去努力保證。
消息中間件選型還有一個考量標準就是儘量貼合團隊自身的技術棧體系,雖然說沒有蹩腳的消息中間件,只有蹩腳的程序員,但是讓一個 C 棧的團隊去深挖 PhxQueue 總比去深挖 Scala 編寫的 Kafka 要容易的多。
消息中間件大道至簡:一發一存一消費,沒有最好的消息中間件,只有最合適的消息中間件。
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章