消息隊列之概論
什么是消息隊列?消息隊列能做什么?消息隊列為什么會出現?再說消息隊列之前我們要先知道什么是消息隊列、能夠做什么、為什么會出現消息隊列?
1、什么是消息隊列
消息隊列是在分布式系統中最常用的且最重要的組件之一,這個分布式系統不是指你的一個服務部署到不同的機器中,如果你是一個相同的服務部署到不同的機器這種不能稱之為分布式系統,准確來說應該說是集群服務,而分布式系統通常是指有很多個不同的服務分別部署到不同的服務器中,
如圖:
,如何在不同的服務中進行快速的數據交互或者調用,通常有兩種方式分別是RPC調用和消息隊列,常見的RPC調用分別有Http、GRPC等。而消息隊列的方式是指由三個重要部分分別是《消息生產者、消息服務中心、消息消費者》組成。
- 生產者: 消息的生產者只負責將消息發送給消息服務中心,它只在意消息是否成功的存儲在了消息隊列服務中。
- 消息服務中心: 消息服務中心其實可以當做一個中間商來看,其實它的作用就是將數據持久化到自己服務內,不在意是誰發送的消息。
- 消息消費者: 消息消費者是指從中間商獲取消息的一個部分,它只在意我是否能拿到消息至於是誰發布的它不在意。
2、消息隊列能做什么
消息隊列可以做:應用解耦、流量削峰、日志收集、消息通訊、事務最終一致性等場景都可以使用消息隊列。
2.1、流量削峰
什么是流量削峰,在互聯網行業中,可能會在某一個時間段網站迎來用戶的請求高峰期的> 情況例如(12306、淘寶雙十一)等,在系統設計之初可能只是簡單寫入數據庫,但是如果一直延續這樣的設計遇到高峰期的請求就會給數據庫帶來巨大的壓力,並發量超出了系統的承載能力可能會引起系統雪崩。當訪問量劇增的> 時候系統一覽可以繼續使用最常見的是使用消息隊列,將短時間的高並發請求持久化到消息隊列服務中,從而實現削平高峰期的請求並發流量,改善系統性能。
2.2、系統解耦
在大型系統的開發過程中會經常碰到 類情況 隨着需求的疊加 各模塊之間逐漸變成了相互調用的關系,這種模塊間緊密關聯的關系就是緊相合 緊相合帶來的問題是對一個模塊的功能變更將導致其關聯模塊發生變化,因此各個模塊難以獨立演要解決這個題,可以在模塊之間調用時增加 個中問層來實現解楠,這也方便了以后的 擴展。所謂解錮,簡單地講,就是一個模塊只關心自己的核心流程,而依賴該棋塊執行結果的其他模塊如果做的不是很重要的事情,有通知即可,無須等待結果 換句話說,基於消息隊列的模型,關心的是通 ,而非處理。
2.3、事務最終一致性
如果系統很小,將兩個表存儲在相同的數據庫中,我們可以通過數據庫的強一致性事務進行管理,如果我們是大型系統需要操作不同的數據庫完成一個業務那么就無法使用數據庫事務來完成了,?業界曾經提出過 個處理分布式事務的規范 XAo XA 主要定義了全事務管理器( Transaction Manager )和局部資源管理器( Resource Manager )之間的接。 XA接口是雙向的系統接口,在事務管理器及 個或多個資源管理器之間形成通信橋梁。兀氣引入事務管理器充當全局事務中的協調者的角色。事務管理器控制着全局事務,管理事務生命周期,並協調資源。資源管理器負責控制和管理實際資源(如數據庫或 JMS 隊列)。目前各主流數據庫都提供了對凡氣規范的支持。它的缺陷是性能很差,不適合高並發和高性能要求的場景。我們可以通過消息隊列來處理事務問題,其實在分布式事務中最主要的是CAP定理,和Base理論,在此不詳細介紹CAP定理和Base理論,具體的可以自行百度。
2.4、日志收集
消息隊列也可以用來做日志收集,在項目運行中日志也是一個很重要的組成部分,可以通過日志跟蹤調試信息、定位問題、用戶操作行為等等。具體的日志分析就需要大數據來進行分析了,日志收集的消息隊列用的最多的就是kafka。
3、消息服務中心的功能與特點
消息隊列它包含了兩個關鍵詞《消息和隊列》,消息是指在不通服務之間傳遞的具體數據,消息可以是各式各樣的;對於隊列的含義我個人理解的其實就是數據結構中隊列的概念,是指先進先出,消息的入隊和出隊並不一定是同步進行的,所以需要一個容器來暫存和處理消息,而消息服務中心就是這個容器。在上面有提到過三個重要的組成部分,分別是:消息生產者->Producer、消息服務中心->Broker、消息消費者->Consumer,除了這些一個好的消息隊列還應該具備以下功能:消息堆積、消息持久化、可靠投遞、消息重復、高可用集群部署等各種問題。
3.1、消息堆積
因為消息隊列的生產者、消費者是兩個分開處理消息的系統,也無法預制兩者對消息的處理速度快慢,一旦在某個時間段內消費者的處理速度沒有跟上生產者發送消息的速度會導致消息處理中心積壓無法及時得到釋放。因此一個好的消息隊列產品需要具備處理這種情況,比如通過設置一個閥值,超過閥值的消息不在放入處理中心等,避免消息中心系統資源耗盡,導致消息中心服務宕機。
3.2、消息持久化
在設計一個消息隊列時,如果生產者的消息到達消息服務中心不做任何處理就直接轉給消費者那么消息服務中心的存在也就失去了意義,無法滿足流量削峰等需求,所以消息服務中心的常規做法都是將消息暫存到消息服務中心本地,然后擇機將消息投遞給消費者,消息的暫存可以在內存中,也可以選擇存儲到磁盤、數據庫、文件等地方。將消息存放到內存中最大的問題就是一旦宕機消息會丟失。如果你的業務場景要求消息不能丟失,那么勢必需要將消息持久化,前面也有提到過持久化方案分為很多種。
3.3、可靠投遞
可靠投遞是指不允許存在消息途中丟失的情況。從消息的整個生命周期來分析的話,消息丟失的情況一般出現在以下過程中:
- 從生產者到消息服務中心
- 從消息服務中心到消息消費者
- 消息中心一旦宕機是否持久化了消息
由於跨越不同系統,中間調用會朋友許多問題,例如網絡問題、系統宕機等不確定的情形,但是對消息發送者來說都是一件事,消息沒有送達,在有些場景下需要保證消息不能丟失,例如網購時訂單支付成功消息不能丟失,否則這筆訂單會卡在未支付環節。
3.4、集群
在大型系統應用中,系統架構一般都需要實現高可用性,用來排除單點故障引起的系統中斷,保證7*24小時不間斷運行,所以消息服務中心需要對集群模式提供支持,集群不僅可以讓消費者和生產者在某個節點宕機的情況下繼續運行,集群之間的多個節點還能夠共享負載,當某台機器或者網絡出現故障時自動進行負載均衡,從而保證多節點來提高消息通信的吞吐量。
4、主流消息服務中間件對比
特性 | ActiveMQ | RabbitMQ | RocketMQ | Kafka |
---|---|---|---|---|
單機吞吐量 | 萬級,與RocketMQ、kafka相比吞吐量略低 | 1W量級,與RocketMQ、kafka相比吞吐量略低 | 10 萬級,支撐高吞吐 | 10 萬級,高吞吐,一般配合大數據類的系統來進行實時數據計算、日志采集等場景 |
Topic數量對吞吐量的影響 | 未知 | 未知 | topic 可以達到幾百/幾千的級別,吞吐量會有較小幅度的下降,這是 RocketMQ 的一大優勢,在同等機器下,可以支撐大量的 topic | topic 從幾十到幾百個時候,吞吐量會大幅度下降,在同等機器下,Kafka 盡量保證 topic 數量不要過多,如果要支撐大規模的 topic,需要增加更多的機器資源 |
時效性 | ms 級 | 微秒級,這是 RabbitMQ 的一大特點,延遲最低 | 毫秒級 | 毫秒 |
可用性 | 可以基於主從架構實現高可用 | 可以基於主從架構實現高可用 | 很高(主從模式) | 非常高,分布式,一個數據多個副本,少數機器宕機,不會丟失數據,不會導致不可用 |
消息丟失 | 有較低的概率丟失數據 | 基本不丟 | 參數優化配置,可以做到 0 丟失 | 參數優化配置,可以做到 0 丟失 |
消費模式 | 推拉 | 推拉 | 拉取 | |
優點 | MQ領域的功能極其完備 | 由於erlang語言的特性,mq 性能較好,高並發;健壯、穩定、易用、跨平台、支持多種語言、文檔齊全;社區活躍度高;路由機制完備 | MQ功能較為完善,還是分布式的,擴展性好,支持10億級別的消息堆積,不會因為堆積導致性能下降 | 性能卓越,單機寫入TPS約在百萬條/秒,最大的優點,就是吞吐量高。 |
缺點 | 官方社區現在對ActiveMQ 5.x維護越來越少,較少在大規模吞吐的場景中使用。 | erlang開發,很難去看懂源碼,基本職能依賴於開源社區的快速維護和修復bug,不利於做二次開發和維護。RabbitMQ吞吐量會低一些,這是因為他做的實現機制比較重。需要學習比較復雜的接口和協議,學習和維護成本較高。 | 支持的客戶端語言不多,目前是java及c++,其中c++不成熟; 社區活躍度一般, 沒有在 mq 核心中去實現JMS等接口,有些系統要遷移需要修改大量代碼 | Kafka單機超過64個隊列/分區,Load會發生明顯的飆高現象,隊列越多,load越高,發送消息響應時間變長 |
總結
消息中間件是非底層操作系統軟件、非業務應用軟件,更不是直接面對最終用戶使用的,不能直接給用戶帶來價值的軟件統稱為中間件。消息中間件關注的是數據的發送和結構,利用高效、可靠的異步消息投遞機制集成成分布式系統。