為什么需要消息隊列?使用消息隊列有什么好處?
點擊下方“Java禿頭哥”,關注公眾號
每天啃一道面試題,只有禿頭,才能更強!
目錄
一、消息隊列的特性
二、為什么需要消息隊列?
三、使用消息隊列有什么好處?
四、為什么需要分布式?
五、分布式環(huán)境下需要解決哪些問題?
六、如何實現(xiàn)?
七、常見消息隊列對比和選型
一、消息隊列的特性
業(yè)務無關,一個具有普適性質(zhì)的消息隊列組件不需要考慮上層的業(yè)務模型,只做好消息的分發(fā)就可以了,上層業(yè)務的不同模塊反而需要依賴消息隊列所定義的規(guī)范進行通信。
FIFO,先投遞先到達的保證是一個消息隊列和一個buffer的本質(zhì)區(qū)別。
容災,對于普適的消息隊列組件來說,節(jié)點的動態(tài)增刪和消息的持久化,都是支持其容災能力的重要基本特性。當然,這個特性對于游戲服務器中大部分應用中的消息隊列來說不是必須的,這個也是跟應用情景有關的,很多時候沒有這種持久化的需求。
性能,這個不必多說了,消息隊列的吞吐量上去了,整個系統(tǒng)的內(nèi)部通信效率也會有提高。
二、為什么需要消息隊列?
當系統(tǒng)中出現(xiàn)“生產(chǎn)“和“消費“的速度或穩(wěn)定性等因素不一致的時候,就需要消息隊列,作為抽象層,彌合雙方的差異?!?消息 ”是在兩臺計算機間傳送的數(shù)據(jù)單位。消息可以非常簡單,例如只包含文本字符串;也可以更復雜,可能包含嵌入對象。消息被發(fā)送到隊列中,“ 消息隊列 ”是在消息的傳輸過程中保存消息的容器 。
舉幾個例子
1)業(yè)務系統(tǒng)觸發(fā)短信發(fā)送申請,但短信發(fā)送模塊速度跟不上,需要將來不及處理的消息暫存一下,緩沖壓力。就可以把短信發(fā)送申請丟到消息隊列,直接返回用戶成功,短信發(fā)送模塊再可以慢慢去消息隊列中取消息進行處理。
2)調(diào)遠程系統(tǒng)下訂單成本較高,且因為網(wǎng)絡等因素,不穩(wěn)定,攢一批一起發(fā)送。
3)任務處理類的系統(tǒng),先把用戶發(fā)起的任務請求接收過來存到消息隊列中,然后后端開啟多個應用程序從隊列中取任務進行處理。
三、使用消息隊列有什么好處?
3.1、提高系統(tǒng)響應速度
使用了消息隊列,生產(chǎn)者一方,把消息往隊列里一扔,就可以立馬返回,響應用戶了。無需等待處理結果。
處理結果可以讓用戶稍后自己來取,如醫(yī)院取化驗單。也可以讓生產(chǎn)者訂閱(如:留下手機號碼或讓生產(chǎn)者實現(xiàn)listener接口、加入監(jiān)聽隊列),有結果了通知。獲得約定將結果放在某處,無需通知。
3.2、提高系統(tǒng)穩(wěn)定性
考慮電商系統(tǒng)下訂單,發(fā)送數(shù)據(jù)給生產(chǎn)系統(tǒng)的情況。電商系統(tǒng)和生產(chǎn)系統(tǒng)之間的網(wǎng)絡有可能掉線,生產(chǎn)系統(tǒng)可能會因維護等原因暫停服務。如果不使用消息隊列,電商系統(tǒng)數(shù)據(jù)發(fā)布出去,顧客無法下單,影響業(yè)務開展。兩個系統(tǒng)間不應該如此緊密耦合。應該通過消息隊列解耦。同時讓系統(tǒng)更健壯、穩(wěn)定。
異步化、解耦、消除峰值
以上三點其實可以用一個例子來解釋——設想有一款MMO游戲,沒有人肉寫的緩存層或者ORM,所有邏輯節(jié)點都直連MySQL,邏輯節(jié)點內(nèi)除了要關注場景、戰(zhàn)斗、交互等復雜邏輯以外,還要有個拼SQL語句的模塊,想想簡直是蛋疼。先考慮一下這樣設計的弊端所在:
邏輯節(jié)點與Db的交互會有大量IO,即使把與Db交互的模塊耦合在邏輯節(jié)點內(nèi),其實現(xiàn)對你來說是黑盒,如果內(nèi)部是同步實現(xiàn)的,那就直接卡你游戲主邏輯,就因為一次存盤操作,玩家們都掉線了,服務器也可以關掉了。
那么我們改進一下,針對1的情況,可以把這個模塊做到一個線程里掛在邏輯節(jié)點上。這樣其實邏輯節(jié)點跟這個Db前端模塊的交互就會基于一個比較原始的消息隊列。但是這樣還有一個壞處,那就是這兩種任務一種是計算密集的(玩家的邏輯處理)、一種是IO密集的(只負責寫入讀取MySQL),搞到一個節(jié)點中,擴展起來會非常麻煩,而且耦合度太高。比如說現(xiàn)在發(fā)現(xiàn)場景放單節(jié)點上有瓶頸,要按場景分節(jié)點,那么這種掛在上面的數(shù)據(jù)模塊怎么跟其他場景的交互呢?
峰值的問題。在分布式系統(tǒng)中,一次分布式事務關聯(lián)的是多個節(jié)點,其中每一個節(jié)點出現(xiàn)問題都會成為整個事務處理流程中的瓶頸。如果邏輯節(jié)點與數(shù)據(jù)庫之間沒有一個起到緩沖作用的節(jié)點,那就是每次操作都要訪問數(shù)據(jù)庫,對于MMO來說,一個玩家上線load幾百K數(shù)據(jù),一個服10萬個玩家上線已經(jīng)足夠搞垮一個mysql節(jié)點了。如果直接搞垮還是比較好的結果,至少是前面的玩家確實登錄上去了并且可以正常游戲,后面的玩家登錄不上。但是很可惜,十年前開始流行的C10K說法就是在講:并發(fā)量上來之后,會造成chain reaction,大量的并發(fā)不會直接掛掉你的mysql節(jié)點,但是會拖慢速度,降低吞吐量,一個玩家的請求由于處理時間太長,導致玩家放棄重試,但是對于后端來說,對該玩家之前的處理過程消耗的資源就全部浪費了,陷入惡性循環(huán)。
所以,這種情景下,一個介于邏輯節(jié)點和db節(jié)點之間的緩存節(jié)點就是理所當然的事情了。這個緩存節(jié)點其實很多時候也可以看作是一個更復雜的消息隊列節(jié)點。
四、為什么需要分布式?
4.1、多系統(tǒng)協(xié)作需要分布式
消息隊列中的數(shù)據(jù)需要在多個系統(tǒng)間共享數(shù)據(jù)才能發(fā)揮價值。所以必須提供分布式通信機制、協(xié)同機制。
4.2、單系統(tǒng)內(nèi)部署環(huán)境需要分布式
單系統(tǒng)內(nèi)部,為了更好的性能、為了避免單點故障,多為集群環(huán)境。集群環(huán)境中,應用運行在多臺服務器的多個JVM中;數(shù)據(jù)也保存在各種類型的數(shù)據(jù)庫或非數(shù)據(jù)庫的多個節(jié)點上。為了滿足多節(jié)點協(xié)作需要,需要提供分布式的解決方案。
五、分布式環(huán)境下需要解決哪些問題?
5.1、并發(fā)問題
需進行良好的并發(fā)控制。確?!熬€程安全“。不要出現(xiàn)一個訂單被出貨兩次。不要出現(xiàn)顧客A下的單,發(fā)貨發(fā)給了顧客B等情況。
5.2、簡單的、統(tǒng)一的操作機制
需定義簡單的,語義明確的,業(yè)務無關的,恰當穩(wěn)妥的統(tǒng)一的訪問方式。
5.3、容錯
控制好單點故障,確保數(shù)據(jù)安全。
5.4、可橫向擴展
可便捷擴容。
六、如何實現(xiàn)?
成熟的消息隊列中間件產(chǎn)品太多了,族繁不及備載。成熟產(chǎn)品經(jīng)過驗證,接口規(guī)范,可擴展性強。
結合事業(yè)環(huán)境因素、組織過程遺產(chǎn)、實施運維考慮、技術路線考慮、開發(fā)人員情況等原因綜合考慮。
七、常見消息隊列對比和選型

出處:http://t.cn/EogJKg4
每天一道面試題、技術知識點,幫助開發(fā)者查缺補漏。
只有禿頭,才能更強!
--END--
【010期】分布式系統(tǒng)接口,如何避免表單的重復提交?
【015期】什么情況用ArrayList or LinkedList呢?
【016期】Java序列化與反序列化三連問:是什么?為什么要?如何做?
【017期】為什么Java線程沒有Running狀態(tài)?
【019期】你能說說Java中Comparable和Comparator的區(qū)別嗎
我精選了45套大廠簡歷模版,需要的朋友關注公眾號并回復 簡歷 領取
點擊關注?? 只有禿頭才能更強


