大家好,我是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 即可下載高清腦圖