訊息佇列技術點梳理(思維導圖版)
訊息佇列作為服務/應用之間的通訊中介軟體,可以起到業務耦合、廣播訊息、保證最終一致性以及錯峰流控(克服短板瓶頸)等作用。本文不打算詳細深入講解訊息佇列,而是體系化的梳理訊息佇列可能涉及的技術點,起到提綱挈領的作用,構造一個巨集觀的概念,使用思維導圖梳理。
再介紹之前,先簡短比較下RPC和訊息佇列。RPC大多屬於請求-應答模式,也包括越來越多響應式正規化,對於需要點對點互動、強事務保證和延遲敏感的服務/應用之間的通訊,RPC是優於訊息佇列的。那麼訊息佇列(下文也簡稱MQ,即Message Queueu)可以看做是一種非同步RPC,把一次RPC變為兩次,進行內容轉存,再在合適的時機投遞出去。訊息佇列中介軟體往往是一個分散式系統,內部元件間的通訊仍然會用到RPC。
目前開源界用的比較多的選型包括,ActiveMQ、RabbitMQ、Kafka、阿里巴巴的Notify、MetaQ、RocketMQ。下文的技術點梳理也是學習借鑑了這些開源元件,然後萃取出一些通用技術點。
關於訊息佇列的體系化認知,見下方的思維導圖。
1. 整體架構
一般分為producer,broker,consumer三者。
2. RPC通訊
詳細參考《體系化認識RPC》(http://www.infoq.com/cn/articles/get-to-know-rpc)。
3. 高效能保證
主要考慮MQ的延遲和吞吐。
高效能投遞方面,分為producer和broker考慮。producer可以同步變非同步、單條變批量保證傳送端高效能,批量傳送的觸發條件可以分為buffer滿或者時間視窗到了。broker可以進行多topic劃分,再多分割槽/queue來進行分治(Divide and Conquer)策略,加大並行度,分散投遞壓力。另外broker對於需要持久化的訊息,可以使用順序IO,page cache,非同步刷盤等技術提高效能,但是非同步刷盤在掉電的情況下,可能會丟失資料,可以結合下面的高可用方案,在資料嚴格不丟和高效能吞吐之間做折中。
高效能消費,即consumer和broker通訊,進行推、拉訊息。使用consumer group水平擴充套件消費能力,需要按照業務場景使用分割槽有序或者無序消費。零拷貝技術節省broker端使用者態到核心態的資料拷貝,直接從page cache傳送到網路,從而最大化傳送效能。consumer批量pull,broker批量push。broker端還可以做訊息過濾,可通過tag或者外掛實現。
4. 高可用保證
主要針對broker而言。
叢集高可用,producer通過broker投遞訊息,所以必然有且僅有一個broker主負責“寫”,選主策略分為自動選主和非主動選擇,自動選主使用分佈一致性元件完成,例如Kafka使用zookeeper,非自動選主,例如RocketMQ依賴多個無狀態的name server。
資料高可用,針對broker持久化積壓訊息場景。可藉助分散式儲存完成,但是往往效能上是個短板,所以大多數主流產品都進行本地IO順序寫,進行主從備份,多副本拷貝保證可用性,例如RocketMQ分為同步雙寫和非同步複製,前者像HDFS一樣,寫完多個副本再返回producer成功,有一定效能損失,但不大,後者最大化效能,但是當主掛的時候,資料有丟失風險。
同樣,MQ叢集也需要考慮跨機房高可用(非“異地多活”),broker的寫高可用,要考慮最小化MTTR,同時不阻塞consumer消費。
5. 擴充套件性保證
採用分治(Divide and Conquer)策略,加大投遞和消費的並行度,多個topic、多個分割槽/queue、多個副本、多個slave或者映象。
6. 協議
producer、consumer和broker通訊的協議,包括AMQP、STOMP、MQTT、HTTP、OpenWire(ActiveMQ)、XMPP、自定義等等。
AMQP是比較全面和複雜的一個協議,包括協議本身以及模型(broker、exchange、routing key等概念),目前RabbitMQ是AMQP訊息佇列最有名的開源實現,有非常多語言已經支援基於AMQP協議與訊息佇列通訊,同時還可以通過外掛支援STOMP、MQTT等協議接入。Kafka、RocketMQ均使用自定義的協議。
7. 消費關係
包括三種
1) 點對點,也就是P2P,FIFO的佇列,可以看做單播。
2) Topic模式,Pub/Sub釋出訂閱。
3) fanout廣播模式。
8. 訊息堆積能力
持久化訊息,如果儲存在本地磁碟,可以使用同步刷盤和非同步刷盤兩種策略。磁碟不能無限堆積,會有清理策略,例如Kafka、RocketMQ都按照時間、資料量進行retention。
非持久化,僅放在記憶體,消費者處理完可選擇刪除掉。
9. 可靠投遞
對於producer,從API和I/O層面可使用同步、非同步,對於吞吐層面可使用單條、批量。fire-and-forget模式,類似UDP,儘管傳送即可。針對可能發生的錯誤,例如連線broker失敗,RPC超時、釋出訊息失敗、釋出後無響應,可選擇忽略或者重發,所以往往重複投遞的情況不可避免。
對於broker,如果要保證資料100%不丟,是可能的,但是需要犧牲下效能和吞吐,使用同步多寫、多副本策略+同步刷盤持久化訊息,可以嚴格保證不丟。另外,broker對於寫入訊息的payload,也會做完整性校驗,例如CRC等。
10. 可靠消費
消費次數,包括at most once、at least once、exactly once,其中前兩個比較好做到,最後的exactly once需要streaming consumer系統和broker端協作完成,例如storm的trident和flink。
推拉模式,push or pull。推模式最小化投遞延遲,但是沒有考慮consumer的承載能力,拉一般是輪詢接收broker的資料,按照consumer自己的能力消費。
消費記錄點,一般每個訊息都有一個offset、ID或者時間戳,consumer可以按照這個offset來進行定點消費以及訊息重放。
訊息確認,consumer消費完成ACK回撥broker或者叢集高可用中介軟體(zk)通知消費進度。
錯誤處理,對於消費失敗的情況,可以回覆NACK,要求重發/requeue訊息,當錯誤超多一定閾值時候,放到死信佇列中。
訊息重複消費,這和消費次數有關係,consumer在某些時候需要做到冪等性,保證重複消費不會引起業務異常。
11. 訊息型別
順序訊息,有序的話,分為分割槽有序或者全域性有序,前者可以按照某個業務ID取模,在傳送端發到不同的分割槽/queue即可,後者往往需要單個佇列才可以滿足。無序消費則可最大化吞吐。
定時訊息,事務訊息,例如RocketMQ均支援。
12. 訊息查詢
目前RocketMQ支援訊息根據msgId查詢。
13. 生態融合
客戶端語言的豐富性,與其他系統的整合度,例如Kafka和大資料技術棧融合很緊密,Spark、Storm、Flink、Kylin都有對應的connector。
14. 管理工具
分散式系統的管理是提高生產效率的必備保障,一個好的系統,如果周邊工具不完善,對於使用者會很不友好,推廣也會有困難。
對於訊息佇列,可以從topic管理、broker管理、叢集管理、許可權/配額管理、多租戶、客戶端工具、監控、報警、控制檯Console UI來全方位進行治理。
出處:http://neoremind.com/2018/03/訊息佇列技術點梳理/
版權申明:內容來源網路,版權歸原創者所有。除非無法確認,我們都會標明作者及出處,如有侵權煩請告知,我們會立即刪除並表示歉意。謝謝。
架構文摘
ID:ArchDigest
網際網路應用架構丨架構技術丨大型網站丨大資料丨機器學習
更多精彩文章,請點選下方:閱讀原文