您好,登錄后才能下訂單哦!
好久沒更新博客,之前對MQ有過研究,現在打算系統的研究下消息隊列。
一、 簡介
1、 是一種跨進程的通信機制,用于上下游傳遞消息。
MQ是一種非常常見的上下游“邏輯解耦+物理解耦”的消息通信服務。
消息發送上游-》 MQ -》消息發送下游。 此情況使用MQ
調用上游-》被調用下游。 此情況不使用MQ。
優點與不足:
2、 不足:
1) 系統更復雜,多了一個MQ組件。
2) 通信時間更長,消息傳遞路徑增長,延時會增加。
3) 消息的可靠性和不重復性不能保證。消息不丟不重難以同時保證。
4) 上游無法知道下游的執行結果。如登錄,上游無法知道是否登錄成功。這種情況使用調用關系。
一、 使用場景
如定時任務。按照執行順序執行。task1,task2,task3。1-2-3的執行順序。可以使用MQ進行解耦。1為發布者,2為訂閱者和發布者,3為訂閱者。
如按照cron執行,需預留時間。有時間浪費。如采用MQ,執行順序和執行時間得到保證。task1的執行時間改變,2、3不需要改變。
1、什么時候不使用MQ?
上游實時關注執行結果
2、什么時候使用MQ?
1)數據驅動的任務依賴
2)上游不關心多下游執行結果
3)異步返回執行時間長
二、 MQ分類
RabbitMQ:
對路由(Routing),負載均衡(Load balance)或者數據持久化都有很好的支持。
Redis
入隊時,當數據比較小時Redis的性能要高于RabbitMQ,而如果數據大小超過了10K,Redis則慢的無法忍受;出隊時,無論數據大小,Redis都表現出非常好的性能,而RabbitMQ的出隊性能則遠低于Redis。
ZeroMQ
號稱最快的消息隊列系統,尤其針對大吞吐量的需求場景。ZMQ能夠實現RabbitMQ不擅長的高級/復雜的隊列,但是開發人員需要自己組合多種技術框架,技術上的復雜度是對這MQ能夠應用成功的挑戰。ZeroMQ具有一個獨特的非中間件的模式,你不需要安裝和運行一個消息服務器或中間件,因為你的應用程序將扮演了這個服務角色。你只需要簡單的引用ZeroMQ程序庫,可以使用NuGet安裝,然后你就可以愉快的在應用程序之間發送消息了。但是ZeroMQ僅提供非持久性的隊列,也就是說如果down機,數據將會丟失。其中,Twitter的Storm中使用ZeroMQ作為數據流的傳輸。
ActiveMQ
是Apache下的一個子項目。 類似于ZeroMQ,它能夠以代理人和點對點的技術實現隊列。同時類似于RabbitMQ,它少量代碼就可以高效地實現高級應用場景。RabbitMQ、ZeroMQ、ActiveMQ均支持常用的多種語言客戶端 C++、Java、.Net,、Python、 Php、 Ruby等。
Kafka
Kafka是Apache下的一個子項目,是一個高性能跨語言分布式Publish/Subscribe消息隊列系統,而Jafka是在Kafka之上孵化而來的,即Kafka的一個升級版。具有以下特性:快速持久化,可以在O(1)的系統開銷下進行消息持久化;高吞吐,在一臺普通的服務器上既可以達到10W/s的吞吐速率;完全的分布式系統,Broker、Producer、Consumer都原生自動支持分布式,自動實現復雜均衡;支持Hadoop數據并行加載,對于像Hadoop的一樣的日志數據和離線分析系統,但又要求實時處理的限制,這是一個可行的解決方案。Kafka通過Hadoop的并行加載機制來統一了在線和離線的消息處理,這一點也是本課題所研究系統所看重的。Apache Kafka相對于ActiveMQ是一個非常輕量級的消息系統,除了性能非常好之外,還是一個工作良好的分布式系統
RocketMQ
阿里巴巴自主研發。
三、 推送類型
場景1:單發送單接收
使用場景:簡單的發送與接收,沒有特別的處理。
場景2:單發送多接收
使用場景:一個發送端,多個接收端,如分布式的任務派發。為了保證消息發送的可靠性,不丟失消息,使消息持久化了。同時為了防止接收端在處理消息時down掉,只有在消息處理完成后才發送ack消息。
場景3:Publish/Subscribe
使用場景:發布、訂閱模式,發送端發送廣播消息,多個接收端接收。
場景4:Routing (按路線發送接收)
使用場景:發送端按routing key發送消息,不同的接收端按不同的routing key接收消息。
場景5:Topics (按topic發送接收)
使用場景:發送端不只按固定的routing key發送消息,而是按字符串“匹配”發送,接收端同樣如此。
四、 數據準確性
1) 可達性:
消息分為上下半場:上半場,發送方將消息發送給MQ。下半場,MQ將消息發送給接收方。
上下半場都有可能出現消息的丟失。為了避免這種情況,需要進行MQ的超時和重傳。
上半場的超時和重傳
MQ上半場如果丟失或者超時,MQ-client-sender內的timer會重發消息,直到期望收到3,如果重傳N次后還未收到,則SendCallback回調發送失敗,需要注意的是,這個過程中MQ-server可能會收到同一條消息的多次重發。
下半場的超時與重傳
MQ下半場如果丟失或者超時,MQ-server內的timer會重發消息,直到成功執行,這個過程可能會重發很多次消息,一般采用指數退避的策略,先隔x秒重發,2x秒重發,4x秒重發,以此類推,需要注意的是,這個過程中MQ-client-receiver也可能會收到同一條消息的多次重發。
MQ-client與MQ-server如何進行消息去重,如何進行架構冪等性設計
2) 冪等性
上半場:
1,發送端MQ-client將消息發給服務端MQ-server
2,服務端MQ-server將消息落地
3,服務端MQ-server回ACK給發送端MQ-client
如果3丟失,發送端MQ-client超時后會重發消息,可能導致服務端MQ-server收到重復消息。
此時重發是MQ-client發起的,消息的處理是MQ-server,為了避免步驟2落地重復的消息,對每條消息,MQ系統內部必須生成一個inner-msg-id,作為去重和冪等的依據,這個內部消息ID的特性是:
(1)全局唯一
(2)MQ生成,具備業務無關性,對消息發送方和消息接收方屏蔽
有了這個inner-msg-id,就能保證上半場重發,也只有1條消息落到MQ-server的DB中,實現上半場冪等。
下半場:
4,服務端MQ-server將消息發給接收端MQ-client
5,接收端MQ-client回ACK給服務端
6,服務端MQ-server將落地消息刪除
需要強調的是,接收端MQ-client回ACK給服務端MQ-server,是消息消費業務方的主動調用行為,不能由MQ-client自動發起,因為MQ系統不知道消費方什么時候真正消費成功。
如果5丟失,服務端MQ-server超時后會重發消息,可能導致MQ-client收到重復的消息。
此時重發是MQ-server發起的,消息的處理是消息消費業務方,消息重發勢必導致業務方重復消費(上例中的一次付款,重復發卡),為了保證業務冪等性,業務消息體中,必須有一個biz-id,作為去重和冪等的依據,這個業務ID的特性是:
(1)對于同一個業務場景,全局唯一
(2)由業務消息發送方生成,業務相關,對MQ透明
(3)由業務消息消費方負責判重,以保證冪等
最常見的業務ID有:支付ID,訂單ID,帖子ID等。
具體到支付購卡場景,發送方必須將支付ID放到消息體中,消費方必須對同一個支付ID進行判重,保證購卡的冪等。
有了這個業務ID,才能夠保證下半場消息消費業務方即使收到重復消息,也只有1條消息被消費,保證了冪等。
免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。