為什麼用或不用消息隊列

最近想從淺入深系統地整理一些關於消息隊列的知識,這裡從為什麼用或為什麼不用消息隊列開始。

為什麼要用消息隊列

1. 異步

想象一種場景,一個有訂閱功能的博客平臺,一個作者有100w個訂閱者(好羨慕這樣的大V),這位大V一但發佈了新博客,需要給這100w位訂閱者發提醒郵件。大V的在編輯完博客,點擊提交的時候需要做兩件事,一個是最基礎的保存博客內容,第二個是要給訂閱者發郵件。如果兩個操作都要在提交請求中同步處理,大V點完提交可能要等到花謝才能收到響應。這種場景就特別適合放到隊列中處理,保存完提交的博客內容,不在請求裡做真實的發郵件操作,而是把發郵件任務那到隊列異步處理,直接響應請求,這樣就可以大大減少請求耗時。

2. 壓力緩衝

還是上面的例子,如果現在平臺舉辦活動,發文章贏大獎,導致瞬間大量的文章發佈,每一篇文章的發佈都意味著至少一次的數據庫操作,而且是寫操作,都要在主庫執行,極端情況下可能會把數據庫壓垮。這時候假如對發文章沒有嚴格的實時性要求,我們也可以把文章內容入庫這個操作也放入隊列,從併發入庫變成順序入庫,這樣就把數據瞬時的高併發寫變成了一段時間內的均勻寫庫。

除上述兩點外,當然還可以業務解耦等很多優點,這裡不再細說。

為什麼不用消息隊列

消息隊列的也存在著明顯的缺點:

1. 不能保證實時性

用消息隊列來處理文章入庫,需要首先和MQ通信,把內容寫到MQ中,可能需要MQ內部的各種路由,最後再交給下游的消費者來做真實的入庫操作,同時如果有很多消息待處理,還要再加上排隊等待處理的時間,算下來肯定要比實時處理延時很大。

2. 執行順序問題

異步是把雙刃劍,帶來快速響應的同時,也會導致編碼上的複雜性,也有一些併發問題不注意的話會導致奇怪的問題。假如有這樣一個場景,發文章時需要做:1. 入庫 2. 通知,現在這兩個操作都分別是放入了各自的隊列裡異步處理,有可能會出現這樣的現象:通知已經發完了,文章內容還沒有入庫。

3. 處理結果問題

還是上面發文章的例子,文章內容入庫異步處理,返回給用戶的只是入隊列是否成功,並不代表真實入庫的成功。所以放入隊列的任務要確保執行成功或將處理結果回調,如果是需要將結果回調的場景,恰好處理失敗,但是之前入隊列時已經返回用戶了處理成功,這種情況需要確定如果處理。需要確保成功的場景可能就要為此引入重試等更復雜的邏輯,重試又會帶來處理邏輯冪等的要求(多次處理不會產生問題,如果包含redis的incrodwv的操作,就會產生問題),這些都會增加代碼的複雜度。

總之,消息隊列在一些場景下必需要用,也有場景是不需要使用,用的話需要關注帶來的各種問題要如果避免或者如何處理。


分享到:


相關文章: