消息隊列(MQ)是一種應用程序對應用程序的通訊方法。應用程序經過寫和檢索出入列隊的針對應用程序的數據(消息)來通訊,而無需專用鏈接來連接它們。消息傳遞指的是程序之間經過在消息中發送數據進行通訊,而不是經過直接調用彼此來通訊,直接調用一般是用於諸如遠程過程調用的技術。排隊指的是應用程序經過隊列來通訊。隊列的使用除去了接收和發送應用程序同時執行的要求。併發
數據驅動的任務依賴異步
什麼是任務依賴,舉個例子,互聯網公司常常在凌晨進行一些數據統計任務,這些任務之間有必定的依賴關係,好比:優化
1)task3 須要使用task2的輸出做爲輸入cdn
2)task2 須要使用task1的輸出做爲輸入blog
這樣的話,tast1, task2, task3之間就有任務依賴關係,必須 task1 先執行,再 task2 執行,再 task3 執行。隊列
不使用MQ同步
對於這類需求,常見的實現方式是,使用 cron 人工排執行時間表:消息隊列
1)task1,0:00 執行,經驗執行時間爲 50 分鐘it
2)task2,1:00 執行(爲 task1 預留 10 分鐘 buffer),經驗執行時間也是 50 分鐘io
3)task3,2:00 執行(爲 task2 預留 10 分鐘 buffer)
這種方法的壞處是:
1)若是有一個任務執行時間超過了預留 buffer 的時間,將會獲得錯誤的結果,由於後置任務不清楚前置任務是否執行成功,此時要手動重跑任務,還有可能要調整排班表
2)總任務的執行時間變長,老是要預留不少 buffer,若是前置任務提早完成,後置任務不會提早開始
3)若是一個任務被多個任務依賴,這個任務將會稱爲關鍵路徑,排班表很難體現依賴關係,容易出錯
4)若是有一個任務的執行時間要調整,將會有多個任務的執行時間要調整
使用 MQ
優化方案是,採用 MQ 解耦:
1)task1 準時開始,結束後發一個「task1 done」的消息
2)task2 訂閱 「task1 done」 的消息,收到消息後第一時間啓動執行,結束後發一個 「task2 done」 的消息
3)task3 同理
採用MQ的優勢是:
1)不須要預留 buffer,上游任務執行完,下游任務總會在第一時間被執行
2)依賴多個任務,被多個任務依賴都很好處理,只須要訂閱相關消息便可
3)有任務執行時間變化,下游任務都不須要調整執行時間
MQ只用來傳遞上游任務執行完成的消息,並不用於傳遞真正的輸入輸出數據。
上游不關心執行結果
上游關注執行結果,但執行時間很長
不使用MQ
上游直接調用下游
1)上游須要同步等待下游執行結果
2)下游系統故障致使上游系統沒法使用
3)下游增長需修改上游代碼
使用MQ
經過使用MQ達到異步、解耦的效果
1)上游無需等待下游執行完畢,加快上游響應速度
2)下游系統故障不會影響上游系統的運行
3)增長下游只需訂閱 MQ
請求高峯期
舉個例子:系統A一天中大部分時間每秒請求併發數量就 100 多個,可是中午12點-1點每秒請求併發量就飆升到 10000 多個,可是系統每秒最大能處理的請求量只有 1000 多。
不使用MQ
使用MQ
經過使用 MQ 達到限流的效果,系統沒法處理的請求會堆積在 MQ 中,高峯期事後系統能夠繼續消費 MQ 中的請求。
1)系統不會由於高峯期的請求量掛掉
引入一項新的技術,在解決現有問題的同時勢必會帶來新的問題。
可用性下降
系統引入的外部依賴越多,越容易掛掉,MQ 掛掉以後會致使整個系統不可用。
複雜度提升
重複消費、消息丟失、消息的順序性等這些都是引入 MQ 以後須要考慮的事情。
一致性問題
A 系統處理完了直接返回成功了,人都覺得你這個請求就成功了;可是問題是,要是 BCD 三個系統那裏,BD 兩個系統寫庫成功了,結果 C 系統寫庫失敗了,就會致使數據不一致。