新聞中心
?1. 引言
2. 消息中間件應(yīng)用背景
2.1 消息中間件基本思想
我們在單個系統(tǒng)中,一些業(yè)務(wù)處理可以順序依次的進(jìn)行。而涉及到跨系統(tǒng)(有時候系統(tǒng)內(nèi)部亦然)的時候,會產(chǎn)生比較復(fù)雜數(shù)據(jù)交互(也可以理解為消息傳遞)的需求,這些數(shù)據(jù)的交互傳遞方式,可以是同步也可以是異步的。在異步傳遞數(shù)據(jù)的情況下,往往需要一個載體,來臨時存儲與分發(fā)消息。在此基礎(chǔ)上,專門針對消息接收、存儲、轉(zhuǎn)發(fā)而設(shè)計與開發(fā)出來的專業(yè)應(yīng)用程序,都可以理解為消息隊列中間件。

目前創(chuàng)新互聯(lián)公司已為1000+的企業(yè)提供了網(wǎng)站建設(shè)、域名、雅安服務(wù)器托管、網(wǎng)站托管、企業(yè)網(wǎng)站設(shè)計、涿鹿網(wǎng)站維護(hù)等服務(wù),公司將堅持客戶導(dǎo)向、應(yīng)用為本的策略,正道將秉承"和諧、參與、激情"的文化,與客戶和合作伙伴齊心協(xié)力一起成長,共同發(fā)展。
引申一下:如果我們自己簡單的使用一張數(shù)據(jù)庫表,來記錄數(shù)據(jù),然后接受數(shù)據(jù)存儲在數(shù)據(jù)表,通過定時任務(wù)再將數(shù)據(jù)表的數(shù)據(jù)分發(fā)出去,那么我們已經(jīng)實現(xiàn)了一個最簡單的消息系統(tǒng)(這就是本地消息表)。
我們可以認(rèn)為消息中間件的基本思想就是 利用高效可靠的消息傳遞機(jī)制進(jìn)行異步的數(shù)據(jù)傳輸。在這個基本思想的指導(dǎo)下,不同的消息中間,因為其側(cè)重場景目的不同,在功能、性能、整體設(shè)計理念上又各有差別。
消息隊列(MQ)本身是實現(xiàn)了生產(chǎn)者到消費者的單向通信模型,RabbitMQ、RocketMQ、Kafka這些常用的MQ都是指實現(xiàn)了這個模型的消息中間件。目前最常用的幾個消息中間件主要有,RabbitMQ、RocketMQ、Kafka(分布式流處理平臺)、Pulsar(分布式消息流平臺)。這里我將兩個流處理平臺納入其中了, 更早的一些其他消息中間件已經(jīng)慢慢淡出視野。業(yè)務(wù)選型的時候我們遵循兩個主要的原則:最大熟悉程度原則(便于運維、使用可靠)、業(yè)務(wù)契合原則(中間件性能可以支撐業(yè)務(wù)體量、滿足業(yè)務(wù)功能需求)。
這幾個常用的消息中間件選型對比,很容易找到,這里就不詳細(xì)描述了。大概說一下:Pulsar目前用的不如 RabbitMQ、RocketMQ、Kafka多。RabbitMQ主要偏重是高可靠消息,RocketMQ性能和功能并重,Kafka主要是在大數(shù)據(jù)處理中應(yīng)用比較多(Pulsar比較類似)。
2.2 引入消息中間件的意義
我們先簡單舉例介紹一下異步、解耦、削峰的意義與價值(參考下面這張流程圖):
對于一個用戶注冊接口,假設(shè)有2個業(yè)務(wù)點,分別是注冊、發(fā)放新人福利,各需要50ms去處理邏輯。如果我們將這兩個業(yè)務(wù)流程耦合在一個接口,那么總計需要100ms處理完成。但是該流程中,用戶注冊時候,可以不用關(guān)心自己的福利是否立即發(fā)放,只要盡快注冊成功返回數(shù)據(jù)即可,后續(xù)新人福利這一部分業(yè)務(wù)可以在主流程之外處理。我們?nèi)绻麑⑵鋭冸x出來,接口主流程中只處理登陸邏輯,并通過MQ推送一條消息,通過異步方式處理后續(xù)的發(fā)放新人福利邏輯,這樣即可保證注冊接口50ms左右即能獲取結(jié)果。
而發(fā)放新人福利的業(yè)務(wù),則通過異步任務(wù)慢慢處理。通過拆分業(yè)務(wù)點,我們已經(jīng)做到解耦,注冊的附屬業(yè)務(wù)中增加或減少功能點都不會影響主流程。另外如果一個業(yè)務(wù)主流程在某個點請求并發(fā)比較高,正好通過異步方式,可以將壓力分散到更長的時間段中去,達(dá)到減輕固定時間段處理壓力的目的,這就是流量削峰。
另外,單線程模型的語言,通常對消息中間件的需求更強(qiáng)烈。多線程模型的語言,或者協(xié)程型語言,雖然可以通過自身的多線程(或協(xié)程)機(jī)制,來實現(xiàn)業(yè)務(wù)內(nèi)部的異步處理,但是考慮到持久化問題以及管理難度,還是成熟的中間件更適合用來做異步數(shù)據(jù)通信,中間件還能實現(xiàn)分布式系統(tǒng)之間的數(shù)據(jù)異步通信。
2.3 消息中間件的應(yīng)用場景
消息中間件的應(yīng)用場景主要有:
-
異步通信:可以用于業(yè)務(wù)系統(tǒng)內(nèi)部的異步通信,也可以用于分布式系統(tǒng)信息交互。
-
系統(tǒng)解耦:將不同性質(zhì)的業(yè)務(wù)進(jìn)行隔離切分,提升性能,主附流程分層,按照重要性進(jìn)行隔離,減少異常影響。
-
流量削峰:間歇性突刺流量分散處理,減少系統(tǒng)壓力,提升系統(tǒng)可用性。
-
分布式事務(wù)一致性:RocketMQ提供的事務(wù)消息功能可以處理分布式事務(wù)一致性(如電商訂單場景)。當(dāng)然,也可以使用分布式事務(wù)中間件。
-
消息順序收發(fā):這是最基礎(chǔ)的功能,先進(jìn)先出,消息隊列必備。
-
延時消息:延遲觸發(fā)的業(yè)務(wù)場景,如下單后延遲取消未支付訂單等。
-
大數(shù)據(jù)處理:日志處理,kafka。
-
分布式緩存同步:消費MySQLbinlog日志進(jìn)行緩存同步,或者業(yè)務(wù)變動直接推送到MQ消費。
所以,如果你的業(yè)務(wù)中有以上列舉的場景,或者類似的功能、性能需求,那么趕快引入「消息中間件」來提升你的業(yè)務(wù)性能吧。
3. 引入消息中間件帶來的一系列問題
雖然消息中間件引入有以上那么多好處,但是使用的時候依然會存在很多問題。例如:
- 引入消息中間件增加了系統(tǒng)復(fù)雜度,怎么使用維護(hù);
- 消息發(fā)送失敗怎么辦(消息丟失);
- 為了確保能發(fā)成功,消息重復(fù)發(fā)送了怎么辦(消息重復(fù));
- 消息在中間件流轉(zhuǎn)出現(xiàn)異常怎么處理;
- 消息消費時候,如果消費流程失敗了怎么處理,還能不能重新從中間件獲取到這條消息;
- 消費失敗如果還能獲取,那會不會出現(xiàn)失敗情況下,一直重復(fù)消費同一條消息,從而流程卡死;
- 消費失敗如果不能再獲取,那么我們該怎么確保這條消息能再次被處理;
- 重復(fù)消費到相同的消息流程怎么處理,會不會導(dǎo)致業(yè)務(wù)異常;
- 那么我們該怎么確保消費流程只成功執(zhí)行一次;
- 對于那些有順序的消息我們應(yīng)該怎么保證發(fā)送和消費的順序一致;
- 消息太多了,怎么保證消費腳本消費速度,以便更得上業(yè)務(wù)的處理需求,避免消息無限積壓;
- 我想要發(fā)送的消息,等上幾秒鐘的時間再消費到,該怎么做;
當(dāng)然我們對于以上的這些問題,針對業(yè)務(wù)開發(fā)者來說,可以進(jìn)行提煉,得到以下幾個重點問題:
- 消息順序性保證
- 避免消息丟失
- 消息的重復(fù)問題
- 消息積壓處理
- 延遲消息處理
4. 問題的解決方案
4.1 消息順序性保證
常規(guī)的消息中間件和流處理中間件,本身設(shè)計一般都能支持順序消息,但是根據(jù)中間件本身不同的設(shè)計目標(biāo),有不同的原理架構(gòu),導(dǎo)致我們業(yè)務(wù)中使用中間件的時候,要針對性做不同的處理。
以下幾個常用消息或流中間件的順序消息設(shè)計以及使用中亂序問題分析:
RabbitMQ:
RabbitMQ的單個隊列(queue)自身,可以保證消息的先進(jìn)先出,在設(shè)計上,RabbitMQ所提供的單個隊列數(shù)據(jù)是存儲在單個broker節(jié)點上的,在開啟鏡像隊列的情況下,鏡像的隊列也只是作為消息副本而存在,服務(wù)依然由主隊列提供。這種情況下在單個隊列上進(jìn)行消費,天然就是順序性的。不過由于單個隊列支持多消費者同時消費,我們在開啟多個消費者消費統(tǒng)一隊列上的數(shù)據(jù)時候,消息分散到多個消費者上,在并發(fā)高的時候,多個消費者無法保證處理消息的順序性。
解決方法就是對于需要強(qiáng)制順序的消息,使用同一個MQ隊列,并且針對單個隊列只開啟一個消費者消費(保證并發(fā)處理時候的順序性,多線程同理)。由此引發(fā)的單個隊列吞吐下降的問題,可以采取kafka的設(shè)計思想,針對單一任務(wù)開啟一組多個隊列,將需要順序的消息按照其固定標(biāo)識(例如:ID)進(jìn)行路由,分散到這一組隊列中,相同標(biāo)識的消息進(jìn)入到相同的隊列,單個隊列使用單個消費者消費,這樣即可以保證消息的順序與吞吐。
如圖所示:
Kafka:
Kafka是流處理中間件,在其設(shè)計中,沒有隊列的概念,消息的收發(fā)依賴于Topic,單個topic可以有多個partition(分區(qū)),這些partition可以分散到多臺broker節(jié)點上,并且partition還可以設(shè)置副本備份以保證其高可用。
Kafka同一個topic可以有多個消費者,甚至消費組。Kafka中消息消費一般使用消費組(消費組可以互不干涉的消費同一個topic下的消息)來進(jìn)行消費,消費組中可以有多個消費者。同一個消費組消費單個topic下的多個partition時,將由kafka來調(diào)節(jié)消費組中消費者與partiton的消費進(jìn)度與均衡。但是有一點是可以保證的:那就是單個partition在同一個消費組中只能被一個消費者消費。
以上的設(shè)計理念下,Kafka內(nèi)部保證在同一個partition中的消息是順序的,不保證topic下的消息的順序性。Kafka的消息生產(chǎn)者發(fā)送消息的時候,是可以選擇將消息發(fā)送到哪個partition中的,我們只要將需要順序處理的消息,發(fā)送到topic下相同的partition,即可保證消息消費的順序性。(多線程語言使用單個消費者,多線程處理數(shù)據(jù)時,需要自己去保證處理的順序,這里略過)。
RocketMQ:
RocketMQ的一些基本概念和原理,可以通過阿里云的官網(wǎng)做一些了解: 什么是消息隊列RocketMQ版?- 消息隊列RocketMQ版 - 阿里云【1】 。
RocketMQ的消息收發(fā)也是基于Topic的,Topic下有多個 Queue, 分布在一個或多個 Broker 上,用來保證消息的高性能收發(fā)( 與Kafka的Topic-Partition機(jī)制 有些類似,但內(nèi)部實現(xiàn)原理并不相同 )。
RocketMQ支持局部順序消息消費,也就是保證同一個消息隊列上的消息順序消費。不支持消息全局順序消費,如果要實現(xiàn)某一個主題的全局順序消息消費,可以將該主題的隊列數(shù)量設(shè)置為1,犧牲高可用性。具體圖解可以參考阿里云文檔: 順序消息2.0 - 消息隊列RocketMQ版 - 阿里云【2】
4.2 避免消息丟失
消息丟失需要分為三部分來看:消息生產(chǎn)者發(fā)送消息到消息中間件的過程不發(fā)生消息丟失,消息在消息中間件中從接受存儲到被消費的過程中消息不丟失, 消息消費的過程中保證能消費到中間件發(fā)送的消息而不會丟失。
生產(chǎn)者發(fā)送消息不丟失:
消息中間件一般都有消息發(fā)送確認(rèn)機(jī)制(ACK), 對于客戶端來說,只要配置好消息發(fā)送需要ACK確認(rèn),就可以根據(jù)返回的結(jié)果來判斷消息是否成功發(fā)送到中間件中。這一步通常與中間件的消息接受存儲流程設(shè)計有關(guān)系。根據(jù)中間件的設(shè)計,我們通常采取的措施如下:
- 開啟MQ的ACK(或confirm)機(jī)制,直接獲知消息發(fā)送結(jié)果
- 開啟消息隊列的持久化機(jī)制(落盤,如果需要特殊設(shè)置的話)
- 中間件本身做好高可用部署
- 消息發(fā)送失敗補償設(shè)計(重試等)
在具體的業(yè)務(wù)設(shè)計中,如果消息發(fā)送失敗,我們可以根據(jù)業(yè)務(wù)重要程度,做相應(yīng)的補償,例如:
- 消息失敗重試機(jī)制(發(fā)送失敗,繼續(xù)重發(fā),可以設(shè)置重試上限)
- 如果依然失敗,根據(jù)消息重要性,選擇降級方案:直接丟棄或者降級到其他中間件或載體(同時需要相應(yīng)的降級補償推送或消費設(shè)計)
消息中間件消息不丟失:
數(shù)消息中間件的消息接收存儲機(jī)制各不相同,但是會根據(jù)其特性設(shè)計,最大限度保證消息不會丟失:
RabbitMQ消息接收與保存:
- RabbitMQ 消息發(fā)送可以開啟發(fā)送者confirm模式,所有消息是否發(fā)送成功都會通知發(fā)送者;
- 需要開啟隊列消息持久化保證消息落盤;
- RabbitMQ通過鏡像隊列來保證消息隊列的高可用,但是鏡像隊列只有Master提供服務(wù),其他slave只提供備份服務(wù);
- master宕機(jī)會從slave中選擇一個成為新的master提供服務(wù);
- master的生產(chǎn)與消費的最新狀態(tài)都會廣播到slave;
RocketMQ消息接受與保存:
- RocketMQ普通消息發(fā)送有三種方式:同步(Sync)發(fā)送、異步(Async)發(fā)送和單向(Oneway)發(fā)送,其區(qū)別與準(zhǔn)確性保證可以參看 「 發(fā)送普通消息(三種方式) - 消息隊列RocketMQ版 - 阿里云」 【3】
- 具體的RocketMQ內(nèi)部設(shè)計的HA機(jī)制是主從同步機(jī)制,消息發(fā)送到Topic下并具體消息隊列的Master Broker中后,會將消息同步到Slave。
- 只有Master Broker才可以接收生產(chǎn)者發(fā)送的消息。而消費者,可以從Master也可以從Slave拉取并消費消息。
Kafka在消息接受到保存所做的設(shè)計有:
- 分區(qū)副本方式的設(shè)計保證消息的高可用,在創(chuàng)建topic的時候都可以設(shè)置分區(qū)副本的數(shù)量;
- 生產(chǎn)者可以選擇接收不同類型的確認(rèn)(ACK),比如在消息被完全提交時候(寫入所有同步副本)的確認(rèn),或者在消息被寫入首領(lǐng)副本時的確認(rèn),或者在消息被發(fā)送到網(wǎng)絡(luò)時確認(rèn);
- Kafka的消息,寫入分區(qū)的時候僅僅是保存在某幾個分區(qū)副本文件系統(tǒng)內(nèi)存中,并不是直接刷到磁盤了,因此宕機(jī)時候,單個副本仍然可能丟失數(shù)據(jù)。Kafka不能保證單個分區(qū)副本的數(shù)據(jù)一定不丟失,而是靠分區(qū)副本機(jī)制來確保消息的完善性(分布到不同的broker上)。
積壓消息保存時效問題
- Kafka對于topic下的數(shù)據(jù),有容量上限、時間上限兩種消息存儲上限規(guī)則,觸發(fā)其中任何一個規(guī)則,都會刪除淘汰之前的消息。這個尤其需要注意。
- RocketMQ,消息在服務(wù)器存儲時間也有上限,達(dá)到上限的消息將會被刪除。也需要做相應(yīng)的考量。
- 受持久化磁盤容量的影響,存儲積壓的數(shù)據(jù)不能超過磁盤的上限。
- 如果業(yè)務(wù)消費有異常,需要給足充足的冗余量,避免因為消費不及時而丟失數(shù)據(jù)。
消費者消費消息不丟失:
- 消息消費時候,也要開啟相應(yīng)的ACK機(jī)制,消息消費成功即ACK(對于Kafka就是更新消費的offset);
- 對于RocketMQ這種有消息重新消費設(shè)計的,需要設(shè)置最大消費次數(shù),嘗試失敗的消息重復(fù)消費。
消息ACK帶來兩個問題:
- 消息消費失敗如果不能ACK可能會導(dǎo)致消息消費無限阻塞在某條消息處;
- 消息失敗重新消費導(dǎo)致消息消費重復(fù)。
無限阻塞的問題,可以參考RocketMQ消費失敗的重試機(jī)制,對消息重試做一定的設(shè)計:
- 在消息體上設(shè)計重試次數(shù)的屬性,消費失敗的消息增加重試次數(shù)后重新發(fā)送到中間件,等待下一次消費,本次消費成功發(fā)回消息直接ACK。
- 消息重試次數(shù)達(dá)到上限之后,如果仍不能成功,則啟用降級方案,將消息存儲到異常信息持久化載體如DB中。
- 手動或者定時任務(wù)補償處理失敗的消息。
消息重復(fù)消費問題參考下一個小節(jié)。
4.3 消息的重復(fù)問題(消費冪等)
在分析常用中間件的時候,我們往往會發(fā)現(xiàn),中間件設(shè)計者將這個問題的處理,下放給中間件使用者,也就是業(yè)務(wù)開發(fā)者了。誠然,業(yè)務(wù)消費處理的邏輯比消息生產(chǎn)者復(fù)雜得多。生產(chǎn)者只需要保證將消息成功發(fā)送到中間件即可,而消費者需要在消費腳本中處理各種復(fù)雜的業(yè)務(wù)邏輯。
解決消息重復(fù)消費的問題,核心是使用唯一標(biāo)識,來標(biāo)記某條消息是否已經(jīng)處理過。具體方案可選的則有很多,比如:
- 使用數(shù)據(jù)庫自增主鍵,或者唯一鍵來保證數(shù)據(jù)不會重復(fù)變動;
- 使用中間狀態(tài),以及狀態(tài)變動有序性來判斷業(yè)務(wù)是否以已經(jīng)被處理;
- 利用一張日志表來記錄已經(jīng)處理成功的消息的 ID,如果新到的消息 ID 已經(jīng)在日志表中,那么就不再處理這條消息;
- 或者消息唯一標(biāo)識,在Redis等NoSQL中維護(hù)一個處理緩存,判斷是否已經(jīng)處理過;
- 如果消費者業(yè)務(wù)流程比較長,則需要開發(fā)者自己保證整個業(yè)務(wù)消費邏輯中數(shù)據(jù)處理的事務(wù)性。
4.4 消息積壓處理
通常我們在引入消息中間件的時候,已經(jīng)會評估與測試消息消費的生產(chǎn)與消費速率,盡量使其達(dá)到平衡。但業(yè)務(wù)也有一些不可預(yù)知的突發(fā)情況,可能會造成消息的大量積壓。在這個時候,我們可以采取如下的方式,來做處理:
臨時緊急擴(kuò)容
- 通過增加消費腳本的方式,提升消費速率,如果下游沒有限制的話,可以很快的減少消息積壓。
- 如果消費者下游數(shù)據(jù)處理能力有限,我們可以考慮建立臨時隊列,通過臨時腳本,將消息快速轉(zhuǎn)移到臨時隊列,優(yōu)先保證線上業(yè)務(wù)能順利貫通,而后開啟更多的消費腳本處理積壓的數(shù)據(jù)。(順序消息需要額外處理,并保證最終處理的順序)
- 優(yōu)化消費腳本的處理速度,突破下游限制,如果有可能,可以考慮批量處理,下游擴(kuò)容等方式。
消息積壓預(yù)防
- 做好業(yè)務(wù)設(shè)計與降級,避免產(chǎn)生無效消息占用資源
- 根據(jù)消息積壓程度,動態(tài)增減消費者數(shù)量,減少消息積壓
- 做好消息積壓處理緊急預(yù)案,異常情況根據(jù)預(yù)案設(shè)計,迅速針對處理
4.5 延遲消息處理
延遲消息這一項功能,在部分MQ中間件中有實現(xiàn)。延時消息和定時消息其實可以互相轉(zhuǎn)換。
RocketMQ:
RocketMQ定時消息不支持任意的時間精度(出于性能考量)。只支持特定級別的延遲消息。消息延遲級別在broker端通過messageDelayLevel配置。其內(nèi)部對每一個延遲級別創(chuàng)建對應(yīng)的消息消費隊列,然后創(chuàng)建對應(yīng)延遲級別的定時任務(wù),從消息消費隊列中將消息拉取并恢復(fù)消息的原主題和原消息消費隊列。
RabbitMQ:
RabbitMQ實現(xiàn)延遲消息通常有兩個方案:一是創(chuàng)建一個消息延遲死信隊列,搭配一個死信轉(zhuǎn)發(fā)隊列來實現(xiàn)消費延時。但是該方式如果前一個消息沒達(dá)到TTL時間,后一個消息即便達(dá)到了,也不會被轉(zhuǎn)發(fā)到轉(zhuǎn)發(fā)隊列中;另一個是使用延時Exchange插件(rabbitmq_delayed_message_exchange),消息在達(dá)到TTL之后才會轉(zhuǎn)發(fā)到對應(yīng)的隊列中并被消費。
Kafka本身不支持延時消息或定時消息, 想要實現(xiàn)消息的延時,需要使用其他的方案。
借助數(shù)據(jù)庫與定時任務(wù)實現(xiàn)延時消息:
常用數(shù)據(jù)庫的索引結(jié)構(gòu)都支持?jǐn)?shù)據(jù)的順序索引。借助數(shù)據(jù)庫可以很方便地實現(xiàn)任意時間消息的延時消費。使用一張表存儲數(shù)據(jù)的消費時間,開啟定時任務(wù),在滿足條件之后將該消息提取出來,后續(xù)轉(zhuǎn)發(fā)到順序隊列去處理或者直接處理都可以(已處理需要做標(biāo)記,后續(xù)不再出現(xiàn)),但是直接處理需要考慮吞吐量和并發(fā)重復(fù)性等問題。不如單個腳本轉(zhuǎn)發(fā)到普通隊列去處理方便。數(shù)據(jù)庫支持的定時任務(wù)消息積壓是可控的,但是吞吐量會有局限。
借助Reids的有序列表實現(xiàn)延時消息:
Reids的有序列表zset結(jié)構(gòu),可以實現(xiàn)延時消息。將消息的消費時間作為分值,把消息添加到zset中。使用 zrangebyscore 命令消費消息 # 命令格式 zrangebysocre key min max withscores limit 0 1 消費最早的一條消息 #min max 分別表示開始的分值與結(jié)束的分值區(qū)間,分別使用 0和當(dāng)前時間戳,可以查出達(dá)到消費時間的消息 # withscores 表示查詢的數(shù)據(jù)要帶分值。limit 后面 就是查詢的起始 offset 和數(shù)量 zrangebyscore key 0 {當(dāng)前時間戳} withscores limit 0 1 。
當(dāng)然,這個方案也有局限性,首先,redis必須配置持久化防止消息丟失(如果配置不合理不能100%保證,但是每個命令都持久化會造成性能下降,需要權(quán)衡);其次,如果延時消息過多會造成消息的積壓形成大key;再次,需要自己做重復(fù)消費和消費失敗的平衡處理(當(dāng)然有可能,還是建議開啟單個消費進(jìn)程將延時消息轉(zhuǎn)移到普通隊列去消費)。
基于時間輪的任務(wù)調(diào)度:
在很多軟件中,都有基于時間輪實現(xiàn)定時任務(wù)的實現(xiàn),使用時間輪以及多級時間輪可以實現(xiàn)延時任務(wù)調(diào)度。如果我們希望自己實現(xiàn)延時任務(wù)隊列,可以考慮使用此算法來實現(xiàn)任務(wù)的調(diào)度,但是需要自己根據(jù)具體的需求去設(shè)計支持任務(wù)的延時上限以及調(diào)度的時間粒度(多層級)。時間輪算法我這里就先不講解了,感興趣的可以自己去搜索了解。
5. 總結(jié)
通過以上幾個小節(jié)的介紹,相信各位已經(jīng)能很自然的理解:消息隊列、異步解耦的功能與核心思想,并且對如何使用MQ來架構(gòu)自己的業(yè)務(wù)有了一定的認(rèn)知。大多數(shù)MQ使用中的問題,只是要求我們多思考,將細(xì)節(jié)思慮周到,以保證業(yè)務(wù)的高可用。甚至,我們還可以在這幾個解決方案中提煉一些核心出來,以便在業(yè)務(wù)中參照類似的思想,優(yōu)化我們的業(yè)務(wù)。比如,消息順序性保證 其核心是順序消息生產(chǎn)者發(fā)送到唯一分區(qū),再維持固定分區(qū)的單消費者順序消費;避免消息丟失的核心是每個步驟的確認(rèn)與降級機(jī)制;消費冪等的核心是唯一性標(biāo)識與步進(jìn)狀態(tài);消息積壓處理的核心是快速響應(yīng)應(yīng)急預(yù)案;延遲消息的核心是消息排序,優(yōu)化點是性能提升。
科學(xué)的方法有歸納和演繹,學(xué)習(xí)問題處理方案的過程中,提煉出相應(yīng)的核心思想,并在使用中演繹,將這些歸納總結(jié)的知識點,再應(yīng)用到業(yè)務(wù)中去,更加得心應(yīng)手的處理相應(yīng)的事務(wù),構(gòu)建出高可用的業(yè)務(wù)架構(gòu),這才是我們最需要做到的。
標(biāo)題名稱:消息中間件應(yīng)用的常見問題與方案
新聞來源:http://www.dlmjj.cn/article/djechos.html


咨詢
建站咨詢
