22面試常問:為什麼需要訊息佇列?使用訊息佇列有什麼好處?

AI喬治發表於2020-11-12

 

目錄

一、訊息佇列的特性
二、為什麼需要訊息佇列?
三、使用訊息佇列有什麼好處?
四、為什麼需要分散式?
五、分散式環境下需要解決哪些問題?
六、如何實現?
七、常見訊息佇列對比和選型

一、訊息佇列的特性

業務無關,一個具有普適性質的訊息佇列元件不需要考慮上層的業務模型,只做好訊息的分發就可以了,上層業務的不同模組反而需要依賴訊息佇列所定義的規範進行通訊。

FIFO,先投遞先到達的保證是一個訊息佇列和一個buffer的本質區別。

容災,對於普適的訊息佇列元件來說,節點的動態增刪和訊息的持久化,都是支援其容災能力的重要基本特性。當然,這個特性對於遊戲伺服器中大部分應用中的訊息佇列來說不是必須的,這個也是跟應用情景有關的,很多時候沒有這種持久化的需求。

效能,這個不必多說了,訊息佇列的吞吐量上去了,整個系統的內部通訊效率也會有提高。

二、為什麼需要訊息佇列?

當系統中出現“生產“和“消費“的速度或穩定性等因素不一致的時候,就需要訊息佇列,作為抽象層,彌合雙方的差異。“ 訊息 ”是在兩臺計算機間傳送的資料單位。訊息可以非常簡單,例如只包含文字字串;也可以更復雜,可能包含嵌入物件。訊息被髮送到佇列中,“ 訊息佇列 ”是在訊息的傳輸過程中儲存訊息的容器 。

舉幾個例子

1)業務系統觸發簡訊傳送申請,但簡訊傳送模組速度跟不上,需要將來不及處理的訊息暫存一下,緩衝壓力。就可以把簡訊傳送申請丟到訊息佇列,直接返回使用者成功,簡訊傳送模組再可以慢慢去訊息佇列中取訊息進行處理。

2)調遠端系統下訂單成本較高,且因為網路等因素,不穩定,攢一批一起傳送。

3)任務處理類的系統,先把使用者發起的任務請求接收過來存到訊息佇列中,然後後端開啟多個應用程式從佇列中取任務進行處理。

三、使用訊息佇列有什麼好處?

3.1、提高系統響應速度

使用了訊息佇列,生產者一方,把訊息往佇列裡一扔,就可以立馬返回,響應使用者了。無需等待處理結果。

處理結果可以讓使用者稍後自己來取,如醫院取化驗單。也可以讓生產者訂閱(如:留下手機號碼或讓生產者實現listener介面、加入監聽佇列),有結果了通知。獲得約定將結果放在某處,無需通知。

3.2、提高系統穩定性

考慮電商系統下訂單,傳送資料給生產系統的情況。電商系統和生產系統之間的網路有可能掉線,生產系統可能會因維護等原因暫停服務。如果不使用訊息佇列,電商系統資料釋出出去,顧客無法下單,影響業務開展。兩個系統間不應該如此緊密耦合。應該通過訊息佇列解耦。同時讓系統更健壯、穩定。

非同步化、解耦、消除峰值

以上三點其實可以用一個例子來解釋——設想有一款MMO遊戲,沒有人肉寫的快取層或者ORM,所有邏輯節點都直連MySQL,邏輯節點內除了要關注場景、戰鬥、互動等複雜邏輯以外,還要有個拼SQL語句的模組,想想簡直是蛋疼。先考慮一下這樣設計的弊端所在:

  • 邏輯節點與Db的互動會有大量IO,即使把與Db互動的模組耦合在邏輯節點內,其實現對你來說是黑盒,如果內部是同步實現的,那就直接卡你遊戲主邏輯,就因為一次存檔操作,玩家們都掉線了,伺服器也可以關掉了。

  • 那麼我們改進一下,針對1的情況,可以把這個模組做到一個執行緒裡掛在邏輯節點上。這樣其實邏輯節點跟這個Db前端模組的互動就會基於一個比較原始的訊息佇列。但是這樣還有一個壞處,那就是這兩種任務一種是計算密集的(玩家的邏輯處理)、一種是IO密集的(只負責寫入讀取MySQL),搞到一個節點中,擴充套件起來會非常麻煩,而且耦合度太高。比如說現在發現場景放單節點上有瓶頸,要按場景分節點,那麼這種掛在上面的資料模組怎麼跟其他場景的互動呢?

  • 峰值的問題。在分散式系統中,一次分散式事務關聯的是多個節點,其中每一個節點出現問題都會成為整個事務處理流程中的瓶頸。如果邏輯節點與資料庫之間沒有一個起到緩衝作用的節點,那就是每次操作都要訪問資料庫,對於MMO來說,一個玩家上線load幾百K資料,一個服10萬個玩家上線已經足夠搞垮一個mysql節點了。如果直接搞垮還是比較好的結果,至少是前面的玩家確實登入上去了並且可以正常遊戲,後面的玩家登入不上。但是很可惜,十年前開始流行的C10K說法就是在講:併發量上來之後,會造成chain reaction,大量的併發不會直接掛掉你的mysql節點,但是會拖慢速度,降低吞吐量,一個玩家的請求由於處理時間太長,導致玩家放棄重試,但是對於後端來說,對該玩家之前的處理過程消耗的資源就全部浪費了,陷入惡性迴圈。

所以,這種情景下,一個介於邏輯節點和db節點之間的快取節點就是理所當然的事情了。這個快取節點其實很多時候也可以看作是一個更復雜的訊息佇列節點。

四、為什麼需要分散式?

4.1、多系統協作需要分散式

訊息佇列中的資料需要在多個系統間共享資料才能發揮價值。所以必須提供分散式通訊機制、協同機制。

4.2、單系統內部署環境需要分散式

單系統內部,為了更好的效能、為了避免單點故障,多為叢集環境。叢集環境中,應用執行在多臺伺服器的多個JVM中;資料也儲存在各種型別的資料庫或非資料庫的多個節點上。為了滿足多節點協作需要,需要提供分散式的解決方案。

五、分散式環境下需要解決哪些問題?

5.1、併發問題

需進行良好的併發控制。確保“執行緒安全“。不要出現一個訂單被出貨兩次。不要出現顧客A下的單,發貨發給了顧客B等情況。

5.2、簡單的、統一的操作機制

需定義簡單的,語義明確的,業務無關的,恰當穩妥的統一的訪問方式。

5.3、容錯

控制好單點故障,確保資料安全。

5.4、可橫向擴充套件

可便捷擴容。

六、如何實現?

成熟的訊息佇列中介軟體產品太多了,族繁不及備載。成熟產品經過驗證,介面規範,可擴充套件性強。

結合事業環境因素、組織過程遺產、實施運維考慮、技術路線考慮、開發人員情況等原因綜合考慮。

七、常見訊息佇列對比和選型

最新2020整理收集的一些面試題(都整理成文件),有很多幹貨,包含mysql,netty,spring,執行緒,spring cloud、jvm、原始碼等詳細講解,也有詳細的學習規劃圖,面試題整理等,需要獲取這些內容的朋友掃描下方二維碼免費獲取:暗號:【CSDN】

 

å¨è¿éæå¥å¾çæè¿°

看完三件事❤️

如果你覺得這篇內容對你還蠻有幫助,我想邀請你幫我三個小忙:

  1. 點贊,轉發,有你們的 『點贊和評論』,才是我創造的動力。

  2. 關注公眾號 『 java爛豬皮 』,不定期分享原創知識。

  3. 同時可以期待後續文章ing?

 

相關文章