什麼是 MQ?
訊息佇列(MQ)是一種應用程式對應用程式的通訊方法。應用程式通過寫和檢索出入列隊的針對應用程式的資料(訊息)來通訊,而無需專用連線來連結它們。訊息傳遞指的是程式之間通過在訊息中傳送資料進行通訊,而不是通過直接呼叫彼此來通訊,直接呼叫通常是用於諸如遠端過程呼叫的技術。排隊指的是應用程式通過佇列來通訊。佇列的使用除去了接收和傳送應用程式同時執行的要求。
為什麼使用 MQ?
使用場景
- 解耦
- 非同步
- 削峰
場景舉例
解耦
-
資料驅動的任務依賴
什麼是任務依賴,舉個例子,網際網路公司經常在凌晨進行一些資料統計任務,這些任務之間有一定的依賴關係,比如:
1)task3 需要使用task2的輸出作為輸入
2)task2 需要使用task1的輸出作為輸入
這樣的話,tast1, task2, task3之間就有任務依賴關係,必須 task1 先執行,再 task2 執行,再 task3 執行。
-
不使用MQ
對於這類需求,常見的實現方式是,使用 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)如果有一個任務的執行時間要調整,將會有多個任務的執行時間要調整
-
使用 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達到非同步、解耦的效果
使用MQ的優點:1)上游無需等待下游執行完畢,加快上游響應速度
2)下游系統故障不會影響上游系統的執行
3)增加下游只需訂閱 MQ
-
削峰
-
請求高峰期
舉個例子:系統A一天中大部分時間每秒請求併發數量就 100 多個,但是中午12點-1點每秒請求併發量就飆升到 10000 多個,但是系統每秒最大能處理的請求量只有 1000 多。
-
不使用MQ
這個時候如果讓系統硬抗會導致系統掛掉 -
使用MQ
通過使用 MQ 達到限流的效果,系統無法處理的請求會堆積在 MQ 中,高峰期過後系統可以繼續消費 MQ 中的請求。
使用MQ的優點:1)系統不會因為高峰期的請求量掛掉
-
引入MQ帶來的問題
引入一項新的技術,在解決現有問題的同時勢必會帶來新的問題。
-
可用性降低
系統引入的外部依賴越多,越容易掛掉,MQ 掛掉之後會導致整個系統不可用。
-
複雜度提高
重複消費、訊息丟失、訊息的順序性等這些都是引入 MQ 之後需要考慮的事情。
-
一致性問題
A 系統處理完了直接返回成功了,人都以為你這個請求就成功了;但是問題是,要是 BCD 三個系統那裡,BD 兩個系統寫庫成功了,結果 C 系統寫庫失敗了,就會導致資料不一致。