文章目錄
一. MQ的作用
當項目中有以下幾種情況,就可以考慮上MQ了
- 服務解耦:分佈式中的模塊之間解耦
- 削峯填谷:當有大量流量的時候,可能來不及處理,需要先把數據存到一個地方,然後在慢慢處理,例如天貓雙11的時候
- 異步化緩衝:異步化處理,不用要求強一致性,最終一致性就好。
二. 使用MQ需要考慮的點
結合自己實際的用戶場景,考慮使用哪種MQ,因爲不同的MQ可能側重點不同
- 生產端可靠性投遞:如果是金融類的場景的話,生產者發送的消息必須要同步到消費者,不能有任何的丟失。
- 消費端冪等性:消費端不能重複消費
- 高可用:可用性是不是良好,用的是什麼模型
- 低延遲:如果對響應有要求,那就得考慮延遲性
- 可靠性:是否可靠
- 擴展性:是否可以輕鬆的擴展
- 堆積能力:消息的堆積能力,如果有大量請求的時候就要考慮好
三. JMS
JMS(Java Message Service)規範,也就是Java消息服務,它定義了Java中訪問消息中間件的接口的規範。在這裏注意哦,JMS只是接口,並沒有給予實現,實現JMS接口的消息中間件稱爲 “JMS Provider”,目前知名的開源 MOM (Message Oriented Middleware,也就是消息中間件)系統包括Apache的ActiveMQ、RocketMQ、Kafka,以及RabbitMQ,可以說他們都 “基本遵循” 或 “參考” JMS規範,都有自己的特點和優勢。
3.1 JMS消息模型
點對點(PTP)
生產者向隊列投遞一條消息,只有一個消費者能夠監聽得到這條消息(PTP),下圖所示:
發佈訂閱(P/S)
發佈訂閱:生產者向隊列投遞一條消息,所有監聽該隊列的消費者都能夠監聽得到這條消息(P/S),下圖所示:
3.2 基礎知識儲備
- 專業術語
- JMS(Java Message Service):實現JMS 接口的消息中間件;
- Provider(MessageProvider):消息的生產者;
- Consumer(MessageConsumer):消息的消費者;
- PTP(Point to Point):即點對點的消息模型,這也是非常經典的模型;
- Pub / Sub(Publish/Subscribe):,即發佈/訂閱的消息模型;
- Queue:隊列目標,也就是我們常說的消息隊列,一般都是會真正的進行物理存儲;
- Topic:主題目標;
- ConnectionFactory:連接工廠,JMS 用它創建連接;
- Connection:JMS 客戶端到JMS Provider 的連接;
- Destination:消息的目的地;
- Session:會話,一個發送或接收消息的線程(這裏Session可以類比Mybatis的Session);
- JMS 消息格式定義:
- StreamMessage 原始值的數據流
- MapMessage 一套名稱/值對
- TextMessage 一個字符串對象
- BytesMessage 一個未解釋字節的數據流
- ObjectMessage 一個序列化的Java對象
四. ActiveMQ
ActiveMQ 是一個完全支持JMS1.1和J2EE 1.4規範的 JMS Provider實現,儘管JMS規範出臺已經是很久的事情了,但是JMS在早些年的 “J2EE應用” 時期扮演着特殊的地位,可以說那個年代ActiveMQ在業界應用最廣泛,當然如果現在想要有更強大的性能和海量數據處理能力,ActiveMQ還需要不斷的升級版本,不斷的提升性能和架構設計的重構。
就算現在我們 80% 以上的業務我們使用ActiveMQ已經足夠滿足需求,其豐富的API、多種集羣構建模式使得他成爲業界老牌消息中間件,在中小型企業中應用廣泛!
當然如果你想針對大規模、高併發應用服務做消息中間件技術選型,譬如淘寶、京東這種大型的電商網站,尤其是雙11這種特殊時間,ActiveMQ可能就顯得力不從心了
4.1 ActiveMQ各項指標
衡量一個MOM,我們主要從三方面考慮即可,即服務性能、存儲堆積能力、可擴展性。
- 服務性能
- ActiveMQ的性能一般,在早期傳統行業爲王的時代還是比較流行的,但現如今面對高併發、大數據的業務場景,往往力不從心!
- 數據存儲
- 默認採用kahadb存儲(索引文件形式存儲),也可以使用高性能的google leveldb(內存數據庫存儲), 或者可以使用MySql、Oracle進程消息存儲(關係型數據庫存儲)。
- 集羣架構
- ActiveMQ 可以與zookeeper進行構建 主備集羣模型,並且多套的主備模型直接可以採用Network的方式構建分佈式集羣。
4.2 ActiveMQ集羣架構模式
ActiveMQ最經典的兩種集羣架構模式,Master-Slave 、Network 集羣模式!
- Master-Slave:就是主從方式,當然這裏要理解爲主備的方式,也就是雙機熱備機制;Master Slave 背後的想法是,消息被複制到slave broker,因此即使master broker遇到了像硬件故障之類的錯誤,你也可以立即切換到slave broker而不丟失任何消息。 Master Slave是目前ActiveMQ推薦的高可靠性和容錯的解決方案。
- Network :這裏可以理解爲網絡通信方式,也可以說叫Network of brokers。這種方式真正解決了分佈式消息存儲和故障轉移、broker切換的問題。可以理解消息會進行均衡;從ActiveMQ1.1版本起,ActiveMQ支持networks of brokers。它支持分佈式的queues和topics。一個broker會相同對待所有的訂閱(subscription):不管他們是來自本地的客戶連接,還是來自遠程broker,它都會遞送有關的消息拷貝到每個訂閱。遠程broker得到這個消息拷貝後,會依次把它遞送到其內部的本地連接上。
4.3 兩種模式的優缺點
- Master-Slave:他是主備的,不能做到類似於es的分片存儲,所以不能做到分佈式的topic、queue,當消息量巨大時,我們的MQ集羣壓力過大,沒辦法滿足分佈式的需求。
- Network:1.這種方案需要兩套或多套(Master-Slave)的集羣模型纔可以搞定,部署非常麻煩。2.Network雖然解決了分佈式消息隊列這個難題,但是還有很多潛在的問題,最典型的就是資源浪費問題,並且也可能達不到所預期的效果。
- 建議:如果是中小型項目,消息量不會特別大的時候,可以用Master-Slave模型,如果要是大型項目的話,換其他的的MQ吧
- 注:以上都是在5.x以下說的,新版的話可能會有變化
五. RabbitMQ集羣架構
5.1 主備模式
一個主/備方案(如果主節點掛了,從節點提供服務,和activeMQ利用Zookeeper做主備一樣,不同的是RabbitMQ是用HaProxy做的)
5.2 遠程模式
遠距離通信和複製,可以實現雙活的一種模式,簡稱Shovel模式
所謂Shovel就是我們可以把消息進行不同數據中心的複製工作,可以跨域的讓兩個MQ集羣互聯
但是這個模式有幾個缺點:
1.配置麻煩
2.穩定性不好
5.3 鏡像模式
集羣模式非常經典的就是Mirror鏡像模式,保證100%數據不丟失
在實際工作中用的最多,並且實現集羣非常的簡單,一般互聯網大廠都會構建這種鏡像集羣模式。
但是這種模式有一個缺點,不支持橫向擴展
5.4 多活模式
這種模式也是實現異地數據複製的主流模式,因爲Shovel模式配置比較複雜,所以一般來說實現異地集羣都是使用這種雙活或者多活模型來實現的
這種模型需要依賴RabbitMQ的federation插件,可以實現持續的可靠的AMQP數據通信,多活模式的配置和應用非常簡單
採用雙中心模式(多中心),那麼在兩套或多套數據中心各部署一套RabbitMQ集羣,各中心的RabbitMQ服務除了需要爲業務提供正常的消息服務外,中心之間還需要實現部分隊列消息共享
5.4.1 Federation插件
Federation插件是一個不需要構建Cluster,而在Brokers之間傳遞消息的高性能插件,Federation插件可以在Brokers或者Clusters之間消息傳輸,鏈接的雙方可以是不同的用戶權限和版本,雙方也可以使用版本不同的RabbitMQ和erlang,Federation插件使用AMQP協議通信,可以接受不連續的傳輸。
六. RocketMQ
RocketMQ是一款分佈式、隊列模型的消息中間件,由阿里巴巴自主研發的一款適用於高併發、高可靠性、海量數據場景的消息中間件。早期開源2.x版本名爲MetaQ;15年迭代3.x版本,更名爲RocketMQ,16年開始貢獻到Apache,經過1年多的孵化,最終成爲Apache頂級的開源項目,更新非常頻繁,社區活躍度也非常高;目前最新版本爲4.5.1-release版本(2019-7-20日前)。RocketMQ參考借鑑了優秀的開源消息中間件Apache Kafka(這也是我們後面課程中重點要講解的內容哦),其消息的路由、存儲、集羣劃分都借鑑了Kafka優秀的設計思路,並結合自身的 “雙十一” 場景進行了合理的擴展和API豐富。
6.1 優秀的能力與支持
- 支持集羣模型、負載均衡、水平擴展能力
- 億級別的消息堆積能力
- 採用零拷貝的原理、順序寫盤、隨機讀(索引文件)
- 豐富的API使用
- 代碼優秀,底層通信框架採用Netty NIO框架
- NameServer 代替 Zookeeper
- 強調集羣無單點,可擴展,任意一點高可用,水平可擴展
- 消息失敗重試機制、消息可查詢
- 開源社區活躍度、是否足夠成熟(經過雙十一考驗)
6.2 專業術語
- Producer:消息生產者,負責產生消息,一般由業務系統負責產生消息。
- Consumer:消息消費者,負責消費消息,一般是後臺系統負責異步消費。
- Push Consumer:Consumer的一種,需要向Consumer對象註冊監聽。
- Pull Consumer:Consumer的一種,需要主動請求Broker拉取消息。
- Producer Group:生產者集合,一般用於發送一類消息。
- Consumer Group:消費者集合,一般用於接受一類消息進行消費。
- Broker : MQ消息服務(中轉角色,用於消息存儲與生產消費轉發)。
6.3 集羣架構模型
RocketMQ爲我們提供了豐富的集羣架構模型,包括單點模式、主從模式、雙主模式、以及生產上使用最多的雙主雙從模式(或者說多主多從模式),在這裏我們僅介紹一下經典的雙主雙從集羣模型,如下圖所示:
- Producer集羣就是生產者集羣(他們在同一個生產者組 Producer Group)
- Consumer集羣就是消費者集羣(他們在同一個消費者組 Consumer Group)
- NameServer集羣作爲超輕量級的配置中心,只做集羣元數據存儲和心跳工作,不必保障節點間數據強一致性,也就是說NameServer集羣是一個多機熱備的概念。
- 對於Broker而言,通常Master與Slave爲一組服務,他們互爲主從節點,通過NameServer與外部的Client端暴露統一的集羣入口。Broker就是消息存儲的核心MQ服務了。
七 Kafka
Kafka是linkedin開源的分佈式消息系統,目前是Apache的頂級項目
Kafka主要特點是基於Pull的模式來處理消息消費,追求高吞吐量,一開始的目的就是用於日誌收集和傳輸。
0.8版本開始支持複製,但不支持事務,對消息的重複,丟失,錯誤沒有嚴格的要求,適合產生大量數據的互聯網服務的數據收集工作。
7.1 Kafka的特點
- 跨平臺
- 分佈式
- 伸縮性
- 實時性
7.2 高性能的原因
- 順序寫:不刪除數據,避免隨機寫
- Page Cache:利用linux的緩存來存儲數據
- 高性能
- 高吞吐
- 後臺異步
- 主動Flush
- 預讀策略
- IO調度
- 零拷貝:
kafka中的消費者在讀取服務端的數據時,需要將服務端的磁盤文件通過網絡發送到消費者進程,網絡發送需要經過幾種網絡節點。如下圖所示:
傳統的讀取文件數據併發送到網絡的步驟如下:
(1)操作系統將數據從磁盤文件中讀取到內核空間的頁面緩存;
(2)應用程序將數據從內核空間讀入用戶空間緩衝區;
(3)應用程序將讀到數據寫回內核空間並放入socket緩衝區;
(4)操作系統將數據從socket緩衝區複製到網卡接口,此時數據才能通過網絡發送。
通常情況下,Kafka的消息會有多個訂閱者,生產者發佈的消息會被不同的消費者多次消費,爲了優化這個流程,Kafka使用了“零拷貝技術”,如下圖所示: