到底什麼時候使用mq
原文地址:http://mp.weixin.qq.com/s/Brd-j3IcljcY7BV01r712Q
一、緣起
一切脫離業務的架構設計與新技術引入都是耍流氓。
引入一個技術之前,首先應該解答的問題是,這個技術解決什麼問題。
就像微服務分層架構之前,應該首先回答,為什麼要引入微服務,微服務究竟解決什麼問題(詳見《網際網路架構為什麼要做微服務?》)。
最近分享了幾篇MQ相關的文章:
不少網友詢問,究竟什麼時候使用MQ,MQ究竟適合什麼場景,故有了此文。
二、MQ是幹嘛的
訊息匯流排(Message Queue),後文稱MQ,是一種跨程式的通訊機制,用於上下游傳遞訊息。
在網際網路架構中,MQ是一種非常常見的上下游“邏輯解耦+物理解耦”的訊息通訊服務。
使用了MQ之後,訊息傳送上游只需要依賴MQ,邏輯上和物理上都不用依賴其他服務。
三、什麼時候不使用訊息匯流排
既然MQ是網際網路分層架構中的解耦利器,那所有通訊都使用MQ豈不是很好?這是一個嚴重的誤區,呼叫與被呼叫的關係,是無法被MQ取代的。
MQ的不足是:
1)系統更復雜,多了一個MQ元件
2)訊息傳遞路徑更長,延時會增加
3)訊息可靠性和重複性互為矛盾,訊息不丟不重難以同時保證
4)上游無法知道下游的執行結果,這一點是很致命的
舉個例子:使用者登入場景,登入頁面呼叫passport服務,passport服務的執行結果直接影響登入結果,此處的“登入頁面”與“passport服務”就必須使用呼叫關係,而不能使用MQ通訊。
無論如何,記住這個結論:呼叫方實時依賴執行結果的業務場景,請使用呼叫,而不是MQ。
四、什麼時候使用MQ
【典型場景一:資料驅動的任務依賴】
什麼是任務依賴,舉個例子,網際網路公司經常在凌晨進行一些資料統計任務,這些任務之間有一定的依賴關係,比如:
1)task3需要使用task2的輸出作為輸入
2)task2需要使用task1的輸出作為輸入
這樣的話,tast1, task2, task3之間就有任務依賴關係,必須task1先執行,再task2執行,載task3執行。
對於這類需求,常見的實現方式是,使用cron人工排執行時間表:
1)task1,0:00執行,經驗執行時間為50分鐘
2)task2,1:00執行(為task1預留10分鐘buffer),經驗執行時間也是50分鐘
3)task3,2:00執行(為task2預留10分鐘buffer)
這種方法的壞處是:
1)如果有一個任務執行時間超過了預留buffer的時間,將會得到錯誤的結果,因為後置任務不清楚前置任務是否執行成功,此時要手動重跑任務,還有可能要調整排班表
2)總任務的執行時間很長,總是要預留很多buffer,如果前置任務提前完成,後置任務不會提前開始
3)如果一個任務被多個任務依賴,這個任務將會稱為關鍵路徑,排班表很難體現依賴關係,容易出錯
4)如果有一個任務的執行時間要調整,將會有多個任務的執行時間要調整
無論如何,採用“cron排班表”的方法,各任務耦合,誰用過誰痛誰知道(採用此法的請評論留言)
優化方案是,採用MQ解耦:
1)task1準時開始,結束後發一個“task1 done”的訊息
2)task2訂閱“task1 done”的訊息,收到訊息後第一時間啟動執行,結束後發一個“task2 done”的訊息
3)task3同理
採用MQ的優點是:
1)不需要預留buffer,上游任務執行完,下游任務總會在第一時間被執行
2)依賴多個任務,被多個任務依賴都很好處理,只需要訂閱相關訊息即可
3)有任務執行時間變化,下游任務都不需要調整執行時間
需要特別說明的是,MQ只用來傳遞上游任務執行完成的訊息,並不用於傳遞真正的輸入輸出資料。
【典型場景二:上游不關心執行結果】
上游需要關注執行結果時要用“呼叫”,上游不關注執行結果時,就可以使用MQ了。
舉個例子,58同城的很多下游需要關注“使用者釋出帖子”這個事件,比如招聘使用者釋出帖子後,招聘業務要獎勵58豆,房產使用者釋出帖子後,房產業務要送2個置頂,二手使用者釋出帖子後,二手業務要修改使用者統計資料。
對於這類需求,常見的實現方式是,使用呼叫關係:
帖子釋出服務執行完成之後,呼叫下游招聘業務、房產業務、二手業務,來完成訊息的通知,但事實上,這個通知是否正常正確的執行,帖子釋出服務根本不關注。
這種方法的壞處是:
1)帖子釋出流程的執行時間增加了
2)下游服務當機,可能導致帖子釋出服務受影響,上下游邏輯+物理依賴嚴重
3)每當增加一個需要知道“帖子釋出成功”資訊的下游,修改程式碼的是帖子釋出服務,這一點是最噁心的,屬於架構設計中典型的依賴倒轉,誰用過誰痛誰知道(採用此法的請評論留言)
優化方案是,採用MQ解耦:
1)帖子釋出成功後,向MQ發一個訊息
2)哪個下游關注“帖子釋出成功”的訊息,主動去MQ訂閱
採用MQ的優點是:
1)上游執行時間短
2)上下游邏輯+物理解耦,除了與MQ有物理連線,模組之間都不相互依賴
3)新增一個下游訊息關注方,上游不需要修改任何程式碼
典型場景三:上游關注執行結果,但執行時間很長
有時候上游需要關注執行結果,但執行結果時間很長(典型的是呼叫離線處理,或者跨公網呼叫),也經常使用回撥閘道器+MQ來解耦。
舉個例子,微信支付,跨公網呼叫微信的介面,執行時間會比較長,但呼叫方又非常關注執行結果,此時一般怎麼玩呢?
一般採用“回撥閘道器+MQ”方案來解耦:
1)呼叫方直接跨公網呼叫微信介面
2)微信返回撥用成功,此時並不代表返回成功
3)微信執行完成後,回撥統一閘道器
4)閘道器將返回結果通知MQ
5)請求方收到結果通知
這裡需要注意的是,不應該由回撥閘道器來呼叫上游來通知結果,如果是這樣的話,每次新增呼叫方,回撥閘道器都需要修改程式碼,仍然會反向依賴,使用回撥閘道器+MQ的方案,新增任何對微信支付的呼叫,都不需要修改程式碼啦。
五、總結
MQ是一個網際網路架構中常見的解耦利器。
什麼時候不使用MQ?
上游實時關注執行結果
什麼時候使用MQ?
1)資料驅動的任務依賴
2)上游不關心多下游執行結果
3)非同步返回執行時間長
相關文章
- 我們在使用jQuery的時候,到底在使用什麼?jQuery
- 什麼時候使用z-index?Index
- 什麼時候使用 Lambda 函式?函式
- 什麼是介面?為什麼使用介面? 什麼時候使用介面?(轉)
- C++中什麼時候用move,什麼時候用forward?C++Forward
- 深入理解go的slice和到底什麼時候該用sliceGo
- MySQL什麼時候會使用內部臨時表?MySql
- 舉例說明你什麼時候會用抽象類,什麼時候更願意使用介面?抽象
- 什麼時候釋出
- 什麼時候呼叫layoutSubviewsView
- 什麼時候能解脫
- SoftReference 到底在什麼時候被回收 ? 如何量化記憶體不足 ?記憶體
- 當我們談論Spring的時候到底在談什麼Spring
- 4 張動圖解釋為什麼(什麼時候)使用 Redux圖解Redux
- python中什麼時候使用自定義類Python
- 天行健課堂 | 什麼時候使用SWOT分析?
- 什麼時候可以考慮使用MySQL MEMORY引擎MySql
- 什麼時候你不應該使用微服務微服務
- T-SQL什麼時候該使用分號SQL
- 區分import 什麼時候使用 花括號{ }Import
- 什麼時候採用socket通訊,什麼時候採用http通訊HTTP
- 新版什麼時候釋出?
- 什麼時候該用vuex?Vue
- 什麼時候該用MongoDB?MongoDB
- 什麼是遷移學習?什麼時候使用遷移學習?遷移學習
- EJB2.0中什麼時候用local interface,什麼時候用remote interface (轉)REM
- 什麼時候你不能使用箭頭函式?函式
- 在JavaScript中什麼時候使用==是正確的?JavaScript
- 什麼時候使用繫結變數效能反而更差變數
- tar -cvf 和 tar cvf 區別,什麼時候使用 " - "
- 什麼時候該使用NoSQL儲存資料庫?SQL資料庫
- 什麼時候在EJB系統中使用XML (轉)XML
- Haskell程式設計精華:什麼時候該註釋,什麼時候不該註釋Haskell程式設計
- 當你在設定裡修改字型大小的時候,到底在修改什麼
- beego 什麼時候支援grpcGoRPC
- python什麼時候縮排Python
- session是什麼時候建立的Session
- Mybatis什麼時候需要宣告jdbcType?MyBatisJDBC