圖解MQ面試_死亡連環炮_再也不怕MQ了

在這裏插入圖片描述
在這裏插入圖片描述
在這裏插入圖片描述
在這裏插入圖片描述
面試題三:如何選型MQ

市面上的MQ有多種,如何選擇合適自己項目的MQ呢?

現在常用的的MQ有ActiveMQ,RabbitMQ,RocketMQ,ZeroMQ,Kafka。網上比較這幾種MQ的文章有很多,大家可以去參考下。我下面就給大家簡單說下。

公司選型MQ主要就在於穩定性、社區活躍性、功能性(當然也不是功能越多越好,也要根據適用場景分析)。

在現如今分佈式大行其道的時候,ZeroMQ對分佈式的不支持對於互聯網企業肯定是不合適的。而ActiveMQ的社區活躍度也不高了,對於技術跟跌如此快的今天也很少企業會去選擇了。而RabbitMQ穩定的維護團隊,可視化的維護界面,低延遲等優點更加受中小型企業的青睞。但是其開發語言死Erlang,對於企業來說就是個黑盒子,完全依賴RbbitMQ高迭代來維護。而RocketMQ來自阿里巴巴家族,現階段其活躍度還是可以的。但是誰也說不好他不會像dubbo一樣被阿里停更。但是RocketMQ用JAVA開發,天生的分佈式架構,10W級以上的吞吐量,低延時,使他更加受大型企業的歡迎。需要企業對其源碼有詳細的瞭解。有精讀源碼的開發人才來對其進行拓展自定義等。Kafka業界大數據的代表作,其功能雖然不多,但是其對分佈式的支持,以及高吞吐量(Kafka單機寫入TPS約在百萬條/秒,消息大小10個字節)使其更加受大數據的歡迎。
在這裏插入圖片描述
在這裏插入圖片描述
在這裏插入圖片描述
在這裏插入圖片描述
在這裏插入圖片描述
總結(一個字一個字的打了好久):
1、爲什麼要用mq?
解耦、削峯、異步
解耦:
做電商的,都會存在幾個系統,商品、訂單、支付、物流、庫存、優惠劵。如果用戶瀏覽商品滿意後,進行下單,一個完整的流程,必然需要訂單系統去調用其他系統。如果一個功能需要提供給多個系統,那麼就需要給每個系統做定製開發,將消息發給各個系統。如果使用MQ則能解決此問題。消費者只需要發送一條消息給MQ,各個消費去訂閱自己感興趣的消息即可。

削峯:
比如mysql的處理能力在每秒2000個請求,如果在高峯期,大量用戶訪問系統,一下子又5000個請求達到mysql,那麼毫無疑問,mysql無法支撐這麼請求的併發,就會掛了。導致服務無法正常使用。如果使用MQ,將請求發送到MQ,消費者根據自己的能力量力而行,則能很好的解決高峯請求量大的情況。

異步:
如果系統間調用時同步的,會導致調用方的整個耗時時間會很長,用戶體驗度將大打折扣。如果用MQ實現異步化,則能很好的解決此問題。

2、既然MQ有那麼多優點,那麼其有什麼缺點呢?
系統增加了MQ,就增加了系統的複雜性,也會引入很多問題,如一致性問題,消息丟失,重複消費,如何保證冪等,消息順序消費,消息積壓等

3、那MQ如何選型呢?
zeroMQ/ActiveMQ/RabbitMQ/RocketMQ/Kafka
zeroMQ其基於C語言,不選擇其原因是其不具備持久化的功能,存在消息丟失的風險,zeroMQ不支持分佈式部署。
ActiveMQ其基於Java語言,早期比較推薦ActiveMQ,但是現在其社區已經不活躍了,所以不太推薦。
RabbitMQ其基於erlang語言,功能完備,社區活躍,吞吐量高,但是其對分佈式部署不是很好。
RocketMQ基於Java語言,阿里系,天生支持分佈式部署,現在的社區活躍度還可以,但是建議中大型企業選擇,因爲其阿里系,誰也說不好他會不會像dubbo一樣,被半路停更。
Kafka基於Scala語言,其高吞吐量,天生支持分佈式部署,使其更加適合大數據領域。

4、MQ如何保證高可用呢?
就拿RabbitMQ來說,RabbitMQ的集羣模式,普通模式和鏡像模式。普通模式由於只有一個節點存儲了元數據和消息,其他節點只是存儲了元數據。如隊列屬性,是否持久化等。而且其他節點不提供寫,只提供讀,只有主節點用來提供寫,其他節點同步其元數據。其他節點提供讀的時候,也是去主節點去拉取消息數據。導致普通集羣只是解決了吞吐量,並沒有解決高可用。一旦主節點掛了,服務將不可用。
而鏡像模式則不同,其每個節點都存儲了相同的數據,可以再某個節點掛了之後選擇其他節點進行寫入,並繼續提供服務。
如果需要在不同的數據中心搬運消息,則需要使用sholve或者federation

至於kafka天生的分佈式架構,讓其對高可用具有良好的支撐,kafka對於一個topic可以指定分配多少個partition。而每個partition至少要有兩個備份。每個partition有一個leader提供讀寫。這樣即使一個備份數據所在服務掛了,其他備份數據會被選爲leader繼續提供服務。而且增加partition的數量就可以明顯提高吞吐量。

5、MQ如何確保消息不丟失呢?
RabbitMQ消息丟失問題分析:
數據的丟失可能發生在生產端,也可能發生在MQ,也可能發生在消費端。所以要分別加以分析。
生產端:如果生產者發送消息,由於網絡問題,沒有發送到MQ就有可能發生消息丟失
那麼如何避免生產端丟失消息呢。一方面可以使用事務,但是事務機制是同步的,會降低吞吐量。另一方面可以考慮使用confirm機制。異步確認消息是否發送成功。producer提供兩個回調函數。ack()和nack()分別用來處理成功發送消息,和失敗發送消息的場景,如失敗則重試發送消息。
MQ端:如果到達了MQ,但是MQ將消息存在在內存,如果MQ掛了,則會導致消息丟失。或者MQ保存消息失敗了,也會導致消息丟失。
所以MQ端可以設置消息持久化到磁盤,避免MQ掛機後消息丟失。另一面MQ和Producer的confirm機制配合使用,當MQ成功將消息存入磁盤後給回調Producer的方法。告知消息是否接受成功。
消費端:如果開啓了autoAck模式,消費者接到了消息時,就會給MQ發送一個通知,告訴MQ已經收到消息了,如果此時消費者還沒有來得及處理消息就掛了,消息丟失。
關閉autoAck模式,手動控制給MQ發送消息的時機,當處理完消息再給MQ發送消息,即使消費者掛了,MQ在監測到此消費者掛了後,會把消息分配給其他消費者消費。此時就會存在消息重複消費的問題,需要消費者做好冪等操作。

kafaka消息丟失問題分析:
同樣會存在以上在生產者、Kafka端、消費者端丟失數據的情況。
舉例:
1、消費者受到Kafka的消息後,會自動提交offset到zookeeper,但是如果這消息在消費前,生產者掛了,那麼這消息不就丟了。
關閉自動提交offset,等到消息被成功消費完後再去更新offset。
2、當Kafka的leader受到消費者發來的消息後,在把消息同步到其他follower之前,leader掛了,那麼重新選舉出leader,此時此leader上不存在那條未被同步過來的消息。那麼這消息就會丟失。
Kafka需要設置幾個參數,來確保消息不丟失。
1/設置每個partition數量必須大於1;
2/設置至少在一個follower同步到leader的數據後再發送ack給producer;
3/producer設置只有kafka把消息同步給了所有的flower後再給自己發確認消息。
4/producer設置重試次數爲無限大,無限次重試消息。確保消息不丟失。
這樣即使leader掛了,也會選舉出那個已經同步了消息的follower爲新leader,確保消息不丟失,即使沒有同步就掛了,但是producer沒有收到ack消息就會不斷的重試發送消息。

6、MQ如何保證消息被消費的順序呢?
rabbitMQ將一個隊列綁定多個消費者,消費者輪詢消息,其消費順序就會發生變化
那麼可以創建多個隊列,讓每個消費者固定消費某個隊列,隊列本身就可以保證順序性。所以消費者就能順序消費消息,確保了消息的順序性。

kafka的每個partition就是給一個消費者消費的,那麼是否就能保證順序性呢(每個partition裏的消息就是順序的)。當消費者開啓多線程去處理partition裏 消息時,就會導致消費亂序。
可以創建多個內存隊列,並按照業務需要把需要保證順序的消息投遞到一個內存隊列裏。每個線程綁定一個內存隊列,這樣一個線程消費消息的順序就能保證了

7、MQ如何避免消息被重複消費呢?
上面分析MQ如何不丟失消息的過程中,提到RabbitMQ在收到消費者確認消息前,檢測到消費者掛了,就會把消息分配到其他消費者消費。如果之前的消費者已經消費過這條消息。則會造成消息重試。
而kafka產生重複消費主要在,kafka認爲消費者掛了後重新rebalance的情況,會出現重複消費。
那如何來保證消息被重複消費後對數據不產生影響呢?就是我們常說的冪等操作。
1/我們新建一個set,當一條消息被消費過就把對應的消息ID存儲起來,當下次再次消費消息,去這個set中比對下,這條消息是否已經在set中;
2/利用數據庫的唯一鍵來保證冪等性

8、MQ消息大量積壓了怎麼辦?
當消費者突然因爲網絡或者宕機沒法提供消費服務的時候,MQ中會迅速堆積大量的消息無法消費。如果大量消息無法消費,如果MQ 還設置了消息持久化,那麼對磁盤對內存來說都是災難。可能就會造成MQ不可用。
解決方式,就是迅速擴容。拿kafka來說,可以新建一個topic,修改線上代碼,把消息都寫到這個topic對應的partition中,然後給這個topic分配幾十個partition,讓十幾個消費者去消費。這樣能快速的消耗掉消息。

9、MQ導致的一致性問題?
當多個系統去消費同一個消息時,其他系統都消費成功了,但是某個系統出錯了,就會導致系統間數據不一致的問題。
使用分佈式事務,提供補償機制,如果出錯則全部執行回滾操作。

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