什麼是消息隊列啊?

大家好,我是walking,原文首發於公衆號@編程大道。

今天我們來聊一聊什麼是消息隊列,爲什麼要用消息隊列,有什麼好處呢?同樣使用消息隊列有什麼壞處?

我們的項目要引入消息隊列了,之前只是聽說使用消息隊列有什麼什麼好處,感覺挺高大上的,自己也只是看過各種消息隊列的技術文章,流行的幾種消息隊列中間件也都自己搭建過,寫過demo,所以現在要引入消息隊列了,好激動啊,要用新技術了。出於大家都不瞭解消息隊列,所以要在項目組內部對各位開發進行一個簡單的科普。以下就是我自己整理的消息隊列的科普知識,希望對大家有所幫助。

一、消息隊列是個什麼東東?

在使用一門新技術之前我們肯定要搞明白這是個什麼東西。消息隊列這個詞想必大家都很熟悉,不管你用沒用過,你應該聽過吧?即便你沒有聽過消息隊列,那隊列你應該聽說過,所以在學習什麼是消息隊列之前我們先來說一下什麼是隊列(queue)。隊列可以說是一個數據結構,可以存儲數據,如下圖,我們從右側(隊尾)插入元素(入隊),從隊頭獲取元素(出隊)。

 

 對於這樣一個數據結構想必大家都不陌生,Java中也實現了好多隊列。例如,創建線程池時我們需要一個阻塞隊列,JDK的Lock機制也需要隊列。

瞭解了隊列之後,我們來看一下什麼是消息隊列,消息隊列就是我們常說的MQ,英文叫Message Queue,是作爲一個單獨的中間件產品存在的,獨立部署。

二、爲什麼要用消息隊列呢?

引入一個新的技術產品,肯定是要考慮爲什麼要用它呢?消息隊列也不列外,說到爲什麼要用,還真是因爲它能在某些場景下發揮奇效。例如:解耦,異步,削峯,這三個詞你也聽說過吧,那下面就就從這三個好處出發,講講到底什麼是解耦,異步,削峯。

2.1 解耦

解耦都不陌生吧,就是降低耦合度,我們都知道Spring的主要目的是降低耦合,那MQ又是如何解耦的呢?如下圖所示,系統A是一個關鍵性的系統,產生數據後需要通知到系統B和系統C做響應的反應,三個系統都寫好了,穩定運行;某一天,系統D也需要在系統A產生數據後作出反應,那就得系統A改代碼,去調系統D的接口,好,改完了,上線了。假設過了某段時間,系統C因爲某些原因,不需要作出反應了,不要系統A調它接口了,就讓系統A把調接口的代碼刪了,系統A的負責人可定會很煩,改來改去,不停的改,不同的測,還得看會不會影響系統B,系統D。沒辦法,這種架構下,就是這樣麻煩。

 

而且這樣還沒考慮異常情況,假如系統A產生了數據,本來需要實時調系統B的,結果系統B宕機了或重啓了,沒調成功咋辦,或者調用返回失敗怎麼辦,系統A是不是要考慮要不要重試?還要開發一套重試機制,系統A要考慮的東西也太多了吧。

那如果使用MQ會是什麼樣的效果呢?如下圖所示,系統A產生數據之後,將該數據寫到MQ中,系統A就不管了,不用關心誰消費,誰不消費,即使是再來一個系統E,或者是系統D不需要數據了,系統A也不需要做任何改變,而系統B、C、D是否消費成功,也不用系統A去關心,通過這樣一種機制,系統A和其他各系統之間的強耦合是不是一下子就解除了,系統A是不是一下子清爽了很多?

 

2.2 異步

同步/異步大家都知道吧,舉個例子,你早上起牀後邊喫早飯邊看電視(異步),而不是喫完飯再看電視(同步)。在上述例子中,沒有使用MQ時,系統A要調系統B、C、D的接口,我們看一下下面的僞代碼想一下是不是這樣

//系統A中的代碼
Data newData = productData();//系統A經過一些邏輯處理後產生了數據,耗時200ms

Response responseB = callSysB(newData);//系統A調系統B接口發送數據,耗時300ms
Response responseC = callSysC(newData);//系統A調系統C接口發送數據,耗時300ms
Response responseD = callSysD(newData);//系統A調系統D接口發送數據,耗時300ms

這樣系統A的用戶做完這個操作就需要等待:

200ms+300ms+300ms+300ms=1100ms=1.1s

點個按鈕等一秒多,用戶體驗得多差啊,客戶可能就會因此而流失掉。

假設使用了MQ呢?系統A就只需要把產生的數據放到MQ裏就行了,就可以立馬返回用戶響應。僞代碼如下:

//系統A中的代碼
Data newData = productData();//系統A經過一些邏輯處理後產生了數據,耗時200ms
writeDateToMQ(newData);//往MQ裏寫消息,耗時50ms

這樣系統A的用戶做完這個操作就只需要等待200ms+50ms=250ms,給用戶的感覺就是一瞬間的事兒,點一下就好了,用戶體驗提升了很多。系統A把數據寫到MQ裏,系統B、C、D就自己去拿,慢慢消費就行了。一般就是一些時效性要求不高的操作,比如下單成功系統A調系統B發下單成功的短信,短信晚幾秒發都是OK的。

2.3 削峯

削峯是什麼意思?大家都知道對於大型互聯網公司,典型的就是電商,時不時的搞一些大促,流量會高於平時幾十倍幾百倍...例如,平時下單也就每秒一二十單,對於現有的架構來說完全不是事兒,那大促的時候呢?每秒就有可能舉個例子是5000單,如果說下單要實時操作數據庫,假設數據庫最大承受一秒2000,那大促的時候一秒5000的話數據庫肯定會被打死的,數據庫一掛導致系統直接不可用,那是多麼嚴重的事情。

所以在這種場景下使用MQ完美的解決了這個問題,下游系統下單時只需要往MQ裏發消息,我的訂單系統可以設定消費的頻率,比如每秒我就消費2000個消息(在數據庫的可承受範圍),不管你下游系統每秒下多少單,我都保持這個速率,既不會影響我訂單系統的數據庫,也不影響你下游系統的下單操作,很好的保護了系統,也提高了下單的吞吐量。

我們都知道,大促也就幾分鐘的事,往多了說是幾個小時吧,咱就說4個小時吧,每秒5000,4小時7200W單往MQ裏寫,訂單系統每秒消費2000單,大促過後,MQ裏會積壓4320W個消息,剩下的就慢慢消費唄。當然了,大促的時候肯定會臨時申請加機器的,每秒消費不止2000。

這就是削峯,將某一段時間的超高流量分攤到更長的一段時間內去消化,避免了流量洪峯擊垮系統。

 

三、使用消息隊列需要注意什麼問題?

既然上面已經說了MQ有那麼多好處,那他肯定也會有不好的地方吧?這是必然的,任何事物都是有兩面性的,沒有十全十美的東西。下面就來說說MQ的缺點或要注意的問題。

缺點:

1、增加了系統的複雜性。

原來系統A、 B、C、D之間就直接用接口調用的方式,現在引進了MQ要考慮很多MQ的問題,如:消息會不會丟失?積壓了很多消息咋辦?MQ滿了咋辦?消息會不會重複?怎麼保證消息順序性等問題。

2、降低了系統的可用性。

各個系統之間強依賴MQ,MQ的可用性就變得非常的關鍵,我還要額外的去保證MQ的高可用,擔心他會掛了。

3、一致性問題。

如:多個系統依賴一個系統發送的消息,如果部分系統消費成功而部分系統消費失敗,可能會導致數據不一致的問題。

 

四、總結

今天我們主要講了3個問題:1)什麼是消息隊列,2)使用消息隊列有什麼好處/爲何要使用消息隊列,3)使用消息隊列會帶來什麼問題/需要注意什麼問題。現在你是不是對消息隊列有了一定的認識呢?

如果對你有所幫助的話,希望不要吝嗇你的贊哦,歡迎關注公衆號@編程大道

 

附言

這裏整理了關於MQ的知識點的一個腦圖,以及上述消息隊列的缺點,特別是對諸如消息會不會丟失?積壓了很多消息咋辦?MQ滿了咋辦?消息會不會重複?怎麼保證消息順序性等問題...的解決方案,需要的小夥伴公衆號後臺回覆:MQ 即可下載高清腦圖

 

 

 

 

 

 

 

 

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章