訊息佇列(Message Queue)基本概念和使用場景分析
阿新 • • 發佈:2019-02-17
背景
之前做日誌收集模組時,用到flume。另外也有的方案,整合kafaka來提升系統可擴充套件性,其中涉及到訊息佇列
當時自己並不清楚為什麼要使用訊息佇列。
而在我自己提出的原始日誌採集方案中不適用訊息佇列
時,有幾個基本問題:1. 日誌檔案上傳過程,有個基本的生產者-消費者
問題;2.
另外系統崩潰時,資料丟失的處理問題。
今天,幾位同事再次談到訊息佇列
這麼個東西,很NB的樣子,我也想弄清楚,OK,搞起。
什麼是訊息佇列
訊息佇列(Message Queue,簡稱MQ),從字面意思上看,本質是個佇列,FIFO先入先出,只不過佇列中存放的內容是message
而已。其主要用途:不同程序Process/執行緒Thread之間通訊。為什麼會產生訊息佇列
- 不同程序(process)之間傳遞訊息時,兩個程序之間耦合程度過高,改動一個程序,引發必須修改另一個程序,為了隔離這兩個程序,在兩程序間抽離出一層(一個模組),所有兩程序之間傳遞的訊息,都必須通過
訊息佇列
來傳遞,單獨修改某一個程序,不會影響另一個; - 不同程序(process)之間傳遞訊息時,為了實現標準化,將訊息的格式規範化了,並且,某一個程序接受的訊息太多,一下子無法處理完,並且也有先後順序,必須對收到的訊息進行排隊,因此誕生了事實上的
訊息佇列
;
不管到底是什麼原因催生了訊息佇列
,總之,上面兩個猜測是其實際應用的典型場景。
為什麼要用
切合前一部分猜測的訊息佇列
產生背景,其主要解決兩個問題:
- 系統解耦:專案開始時,無法確定最終需求,不同程序間,新增一層,實現解耦,方便今後的擴充套件。
- 訊息快取:系統中,不同程序處理訊息速度不同,MQ,可以實現不同Process之間的緩衝,即,寫入MQ的速度可以儘可能地快,而處理訊息的速度可以適當調整(或快、或慢)。
下面針對系統解耦、訊息快取兩點,來分析實際應用訊息佇列
過程中,可能遇到的問題。虛擬場景:Process_A通過訊息佇列MQ_1向Process_B傳遞訊息,幾個問題:
- 針對MQ_1中一條訊息message_1,如何確保Process_B從MQ_1中只取一次message_1,不會重複多次取出message_1?
- 如果MQ_1中message_1已經被Process_B取出,正在處理的關鍵時刻,Process_B崩潰了,哭啊,我的問題是,如果重啟Process_B,是否會丟失message_1?
不要著急,閱讀了下面的簡要介紹後,水到渠成,上面幾個問題就可以解決了。 訊息佇列有如下幾個好處,這大都是由其系統解耦和訊息快取兩點擴充套件而來的:
- 提升系統可靠性:
- 冗餘:Process_B崩潰之後,資料並不會丟失,因為MQ多采用
put-get-delete
模式,即,僅當確認message被完成處理之後,才從MQ中移除message; - 可恢復:MQ實現解耦,部分程序崩潰,不會拖累整個系統癱瘓,例,Process_B崩潰之後,Process_A仍可向MQ中新增message,並等待Process_B恢復;
- 可伸縮:有較強的峰值處理能力,通常應用會有突發的訪問流量上升情況,使用足夠的硬體資源時刻待命,空閒時刻較長,資源浪費,而
訊息佇列
卻能夠平滑峰值流量,緩解系統元件的峰值壓力;
- 冗餘:Process_B崩潰之後,資料並不會丟失,因為MQ多采用
- 提升系統可擴充套件性:
- 調整模組:由於實現解耦,可以很容易調整,訊息入隊速率、訊息處理速率、增加新的Process;
- 其他:
- 單次送達:保證MQ中一個message被處理一次,並且只被處理一次。本質:get獲取一個message後,這一message即被預定,同一程序不會再次獲取這一message;當且僅當程序處理完這一message後,MQ中會delete這個message。否則,過一段時間後,這一message自動解除被預訂狀態,程序能夠重新預定這個message;
- 排序保證:即,滿足佇列的FIFO,先入先出策略;
- 非同步通訊:很多場景下,不會立即處理訊息,這是,可以在MQ中儲存message,並在某一時刻再進行處理;
- 資料流的階段效能定位:獲取使用者某一操作的各個階段(通過message來標識),捕獲不同階段的耗時,可用於定位系統瓶頸。