全網最全、最新消息中間件面試題(2020最新版)

rabbitmq.jpg
原文:https://thinkwon.blog.csdn.ne...node

爲何使用MQ?MQ的優勢

簡答sql

  1. 異步處理 - 相比於傳統的串行、並行方式,提升了系統吞吐量。
  2. 應用解耦 - 系統間經過消息通訊,不用關心其餘系統的處理。
  3. 流量削鋒 - 能夠經過消息隊列長度控制請求量;能夠緩解短期內的高併發請求。
  4. 日誌處理 - 解決大量日誌傳輸。
  5. 消息通信 - 消息隊列通常都內置了高效的通訊機制,所以也能夠用在純的消息通信。好比實現點對點消息隊列,或者聊天室等。

詳答數據庫

主要是:解耦、異步、削峯。segmentfault

解耦:A 系統發送數據到 BCD 三個系統,經過接口調用發送。若是 E 系統也要這個數據呢?那若是 C 系統如今不須要了呢?A 系統負責人幾乎崩潰…A 系統跟其它各類亂七八糟的系統嚴重耦合,A 系統產生一條比較關鍵的數據,不少系統都須要 A 系統將這個數據發送過來。若是使用 MQ,A 系統產生一條數據,發送到 MQ 裏面去,哪一個系統須要數據本身去 MQ 裏面消費。若是新系統須要數據,直接從 MQ 裏消費便可;若是某個系統不須要這條數據了,就取消對 MQ 消息的消費便可。這樣下來,A 系統壓根兒不須要去考慮要給誰發送數據,不須要維護這個代碼,也不須要考慮人家是否調用成功、失敗超時等狀況。瀏覽器

就是一個系統或者一個模塊,調用了多個系統或者模塊,互相之間的調用很複雜,維護起來很麻煩。可是其實這個調用是不須要直接同步調用接口的,若是用 MQ 給它異步化解耦。安全

異步:A 系統接收一個請求,須要在本身本地寫庫,還須要在 BCD 三個系統寫庫,本身本地寫庫要 3ms,BCD 三個系統分別寫庫要 300ms、450ms、200ms。最終請求總延時是 3 + 300 + 450 + 200 = 953ms,接近 1s,用戶感受搞個什麼東西,慢死了慢死了。用戶經過瀏覽器發起請求。若是使用 MQ,那麼 A 系統連續發送 3 條消息到 MQ 隊列中,假如耗時 5ms,A 系統從接受一個請求到返回響應給用戶,總時長是 3 + 5 = 8ms。服務器

削峯:減小高峯時期對服務器壓力。網絡

消息隊列有什麼優缺點?RabbitMQ有什麼優缺點?

優勢上面已經說了,就是在特殊場景下有其對應的好處,解耦、異步、削峯。架構

缺點有如下幾個:併發

系統可用性下降

原本系統運行好好的,如今你非要加入個消息隊列進去,那消息隊列掛了,你的系統不是呵呵了。所以,系統可用性會下降;

系統複雜度提升

加入了消息隊列,要多考慮不少方面的問題,好比:一致性問題、如何保證消息不被重複消費、如何保證消息可靠性傳輸等。所以,須要考慮的東西更多,複雜性增大。

一致性問題

A 系統處理完了直接返回成功了,人都覺得你這個請求就成功了;可是問題是,要是 BCD 三個系統那裏,BD 兩個系統寫庫成功了,結果 C 系統寫庫失敗了,咋整?你這數據就不一致了。

因此消息隊列實際是一種很是複雜的架構,你引入它有不少好處,可是也得針對它帶來的壞處作各類額外的技術方案和架構來規避掉,作好以後,你會發現,媽呀,系統複雜度提高了一個數量級,也許是複雜了 10 倍。可是關鍵時刻,用,仍是得用的。

大家公司生產環境用的是什麼消息中間件?

這個首先你能夠說下大家公司選用的是什麼消息中間件,好比用的是RabbitMQ,而後能夠初步給一些你對不一樣MQ中間件技術的選型分析。

舉個例子:好比說ActiveMQ是老牌的消息中間件,國內不少公司過去運用的仍是很是普遍的,功能很強大。

可是問題在於無法確認ActiveMQ能夠支撐互聯網公司的高併發、高負載以及高吞吐的複雜場景,在國內互聯網公司落地較少。並且使用較多的是一些傳統企業,用ActiveMQ作異步調用和系統解耦。

而後你能夠說說RabbitMQ,他的好處在於能夠支撐高併發、高吞吐、性能很高,同時有很是完善便捷的後臺管理界面可使用。

另外,他還支持集羣化、高可用部署架構、消息高可靠支持,功能較爲完善。

並且通過調研,國內各大互聯網公司落地大規模RabbitMQ集羣支撐自身業務的case較多,國內各類中小型互聯網公司使用RabbitMQ的實踐也比較多。

除此以外,RabbitMQ的開源社區很活躍,較高頻率的迭代版本,來修復發現的bug以及進行各類優化,所以綜合考慮事後,公司採起了RabbitMQ。

可是RabbitMQ也有一點缺陷,就是他自身是基於erlang語言開發的,因此致使較爲難以分析裏面的源碼,也較難進行深層次的源碼定製和改造,畢竟須要較爲紮實的erlang語言功底才能夠。

而後能夠聊聊RocketMQ,是阿里開源的,通過阿里的生產環境的超高併發、高吞吐的考驗,性能卓越,同時還支持分佈式事務等特殊場景。

並且RocketMQ是基於Java語言開發的,適合深刻閱讀源碼,有須要能夠站在源碼層面解決線上生產問題,包括源碼的二次開發和改造。

另外就是Kafka。Kafka提供的消息中間件的功能明顯較少一些,相對上述幾款MQ中間件要少不少。

可是Kafka的優點在於專爲超高吞吐量的實時日誌採集、實時數據同步、實時數據計算等場景來設計。

所以Kafka在大數據領域中配合實時計算技術(好比Spark Streaming、Storm、Flink)使用的較多。可是在傳統的MQ中間件使用場景中較少採用。

Kafka、ActiveMQ、RabbitMQ、RocketMQ 有什麼優缺點?

image.png

綜上,各類對比以後,有以下建議:

通常的業務系統要引入 MQ,最先你們都用 ActiveMQ,可是如今確實你們用的很少了,沒通過大規模吞吐量場景的驗證,社區也不是很活躍,因此你們仍是算了吧,我我的不推薦用這個了;

後來你們開始用 RabbitMQ,可是確實 erlang 語言阻止了大量的 Java 工程師去深刻研究和掌控它,對公司而言,幾乎處於不可控的狀態,可是確實人家是開源的,比較穩定的支持,活躍度也高;

不過如今確實愈來愈多的公司會去用 RocketMQ,確實很不錯,畢竟是阿里出品,但社區可能有忽然黃掉的風險(目前 RocketMQ 已捐給 Apache,但 GitHub 上的活躍度其實不算高)對本身公司技術實力有絕對自信的,推薦用 RocketMQ,不然回去老老實實用 RabbitMQ 吧,人家有活躍的開源社區,絕對不會黃。

因此中小型公司,技術實力較爲通常,技術挑戰不是特別高,用 RabbitMQ 是不錯的選擇;大型公司,基礎架構研發實力較強,用 RocketMQ 是很好的選擇。

若是是大數據領域的實時計算、日誌採集等場景,用 Kafka 是業內標準的,絕對沒問題,社區活躍度很高,絕對不會黃,況且幾乎是全世界這個領域的事實性規範。

MQ 有哪些常見問題?如何解決這些問題?

MQ 的常見問題有:

消息的順序問題
消息的重複問題

消息的順序問題

消息有序指的是能夠按照消息的發送順序來消費。

假如生產者產生了 2 條消息:M一、M2,假定 M1 發送到 S1,M2 發送到 S2,若是要保證 M1 先於 M2 被消費,怎麼作?
img

解決方案:

(1)保證生產者 - MQServer - 消費者是一對一對一的關係

img

缺陷:

  • 並行度就會成爲消息系統的瓶頸(吞吐量不夠)
  • 更多的異常處理,好比:只要消費端出現問題,就會致使整個處理流程阻塞,咱們不得不花費更多的精力來解決阻塞的問題。 (2)經過合理的設計或者將問題分解來規避。
  • 不關注亂序的應用實際大量存在
  • 隊列無序並不意味着消息無序 因此從業務層面來保證消息的順序而不只僅是依賴於消息系統,是一種更合理的方式。

消息的重複問題

形成消息重複的根本緣由是:網絡不可達。

因此解決這個問題的辦法就是繞過這個問題。那麼問題就變成了:若是消費端收到兩條同樣的消息,應該怎樣處理?

消費端處理消息的業務邏輯保持冪等性。只要保持冪等性,無論來多少條重複消息,最後處理的結果都同樣。保證每條消息都有惟一編號且保證消息處理成功與去重表的日誌同時出現。利用一張日誌表來記錄已經處理成功的消息的 ID,若是新到的消息 ID 已經在日誌表中,那麼就再也不處理這條消息。

什麼是RabbitMQ?

RabbitMQ是一款開源的,Erlang編寫的,基於AMQP協議的消息中間件

rabbitmq 的使用場景
(1)服務間異步通訊

(2)順序消費

(3)定時任務

(4)請求削峯

RabbitMQ基本概念
  • Broker: 簡單來講就是消息隊列服務器實體
  • Exchange: 消息交換機,它指定消息按什麼規則,路由到哪一個隊列
  • Queue: 消息隊列載體,每一個消息都會被投入到一個或多個隊列
  • Binding: 綁定,它的做用就是把exchange和queue按照路由規則綁定起來
  • Routing Key: 路由關鍵字,exchange根據這個關鍵字進行消息投遞
  • VHost: vhost 能夠理解爲虛擬 broker ,即 mini-RabbitMQ server。其內部均含有獨立的 queue、exchange 和 binding 等,但最最重要的是,其擁有獨立的權限系統,能夠作到 vhost 範圍的用戶控制。固然,從 RabbitMQ 的全局角度,vhost 能夠做爲不一樣權限隔離的手段(一個典型的例子就是不一樣的應用能夠跑在不一樣的 vhost 中)。
  • Producer: 消息生產者,就是投遞消息的程序
  • Consumer: 消息消費者,就是接受消息的程序
  • Channel: 消息通道,在客戶端的每一個鏈接裏,可創建多個channel,每一個channel表明一個會話任務

由Exchange、Queue、RoutingKey三個才能決定一個從Exchange到Queue的惟一的線路。

RabbitMQ的工做模式

一.simple模式(即最簡單的收發模式)

img

1.消息產生消息,將消息放入隊列

2.消息的消費者(consumer) 監聽 消息隊列,若是隊列中有消息,就消費掉,消息被拿走後,自動從隊列中刪除(隱患 消息可能沒有被消費者正確處理,已經從隊列中消失了,形成消息的丟失,這裏能夠設置成手動的ack,但若是設置成手動ack,處理完後要及時發送ack消息給隊列,不然會形成內存溢出)。

二.work工做模式(資源的競爭)
img

1.消息產生者將消息放入隊列消費者能夠有多個,消費者1,消費者2同時監聽同一個隊列,消息被消費。C1 C2共同爭搶當前的消息隊列內容,誰先拿到誰負責消費消息(隱患:高併發狀況下,默認會產生某一個消息被多個消費者共同使用,能夠設置一個開關(syncronize) 保證一條消息只能被一個消費者使用)。

**三.publish/subscribe發佈訂閱(共享資源)

img

一、每一個消費者監聽本身的隊列;

二、生產者將消息發給broker,由交換機將消息轉發到綁定此交換機的每一個隊列,每一個綁定交換機的隊列都將接收到消息。

四.routing路由模式
img

1.消息生產者將消息發送給交換機按照路由判斷,路由是字符串(info) 當前產生的消息攜帶路由字符(對象的方法),交換機根據路由的key,只能匹配上路由key對應的消息隊列,對應的消費者才能消費消息;

2.根據業務功能定義路由字符串

3.從系統的代碼邏輯中獲取對應的功能字符串,將消息任務扔到對應的隊列中。

4.業務場景:error 通知;EXCEPTION;錯誤通知的功能;傳統意義的錯誤通知;客戶通知;利用key路由,能夠將程序中的錯誤封裝成消息傳入到消息隊列中,開發者能夠自定義消費者,實時接收錯誤;

五.topic 主題模式(路由模式的一種)

img

1.星號井號表明通配符

2.星號表明多個單詞,井號表明一個單詞

3.路由功能添加模糊匹配

4.消息產生者產生消息,把消息交給交換機

5.交換機根據key的規則模糊匹配到對應的隊列,由隊列的監聽消費者接收消息消費

(在個人理解看來就是routing查詢的一種模糊匹配,就相似sql的模糊查詢方式)

如何保證RabbitMQ消息的順序性?

拆分多個 queue,每一個 queue 一個 consumer,就是多一些 queue 而已,確實是麻煩點;或者就一個 queue 可是對應一個 consumer,而後這個 consumer 內部用內存隊列作排隊,而後分發給底層不一樣的 worker 來處理。

消息如何分發?

若該隊列至少有一個消費者訂閱,消息將以循環(round-robin)的方式發送給消費者。每條消息只會分發給一個訂閱的消費者(前提是消費者可以正常處理消息並進行確認)。經過路由可實現多消費的功能

消息怎麼路由?

消息提供方->路由->一至多個隊列消息發佈到交換器時,消息將擁有一個路由鍵(routing key),在消息建立時設定。經過隊列路由鍵,能夠把隊列綁定到交換器上。消息到達交換器後,RabbitMQ 會將消息的路由鍵與隊列的路由鍵進行匹配(針對不一樣的交換器有不一樣的路由規則);

經常使用的交換器主要分爲一下三種:

fanout:若是交換器收到消息,將會廣播到全部綁定的隊列上

direct:若是路由鍵徹底匹配,消息就被投遞到相應的隊列

topic:可使來自不一樣源頭的消息可以到達同一個隊列。 使用 topic 交換器時,可使用通配符

消息基於什麼傳輸?

因爲 TCP 鏈接的建立和銷燬開銷較大,且併發數受系統資源限制,會形成性能瓶頸。RabbitMQ 使用信道的方式來傳輸數據。信道是創建在真實的 TCP 鏈接內的虛擬鏈接,且每條 TCP 鏈接上的信道數量沒有限制。

如何保證消息不被重複消費?或者說,如何保證消息消費時的冪等性?

先說爲何會重複消費:正常狀況下,消費者在消費消息的時候,消費完畢後,會發送一個確認消息給消息隊列,消息隊列就知道該消息被消費了,就會將該消息從消息隊列中刪除;

可是由於網絡傳輸等等故障,確認信息沒有傳送到消息隊列,致使消息隊列不知道本身已經消費過該消息了,再次將消息分發給其餘的消費者。

針對以上問題,一個解決思路是:保證消息的惟一性,就算是屢次傳輸,不要讓消息的屢次消費帶來影響;保證消息等冪性;

好比:在寫入消息隊列的數據作惟一標示,消費消息時,根據惟一標識判斷是否消費過;

假設你有個系統,消費一條消息就往數據庫裏插入一條數據,要是你一個消息重複兩次,你不就插入了兩條,這數據不就錯了?可是你要是消費到第二次的時候,本身判斷一下是否已經消費過了,如果就直接扔了,這樣不就保留了一條數據,從而保證了數據的正確性。

如何確保消息正確地發送至 RabbitMQ? 如何確保消息接收方消費了消息?

發送方確認模式

將信道設置成 confirm 模式(發送方確認模式),則全部在信道上發佈的消息都會被指派一個惟一的 ID。

一旦消息被投遞到目的隊列後,或者消息被寫入磁盤後(可持久化的消息),信道會發送一個確認給生產者(包含消息惟一 ID)。

若是 RabbitMQ 發生內部錯誤從而致使消息丟失,會發送一條 nack(notacknowledged,未確認)消息。

發送方確認模式是異步的,生產者應用程序在等待確認的同時,能夠繼續發送消息。當確認消息到達生產者應用程序,生產者應用程序的回調方法就會被觸發來處理確認消息。

接收方確認機制

消費者接收每一條消息後都必須進行確認(消息接收和消息確認是兩個不一樣操做)。只有消費者確認了消息,RabbitMQ 才能安全地把消息從隊列中刪除。

這裏並無用到超時機制,RabbitMQ 僅經過 Consumer 的鏈接中斷來確認是否須要從新發送消息。也就是說,只要鏈接不中斷,RabbitMQ 給了 Consumer 足夠長的時間來處理消息。保證數據的最終一致性;

下面羅列幾種特殊狀況

若是消費者接收到消息,在確認以前斷開了鏈接或取消訂閱,RabbitMQ 會認爲消息沒有被分發,而後從新分發給下一個訂閱的消費者。(可能存在消息重複消費的隱患,須要去重)
若是消費者接收到消息卻沒有確認消息,鏈接也未斷開,則 RabbitMQ 認爲該消費者繁忙,將不會給該消費者分發更多的消息。

如何保證RabbitMQ消息的可靠傳輸?

消息不可靠的狀況多是消息丟失,劫持等緣由;

丟失又分爲:生產者丟失消息、消息列表丟失消息、消費者丟失消息;

生產者丟失消息:從生產者弄丟數據這個角度來看,RabbitMQ提供transaction和confirm模式來確保生產者不丟消息;

transaction機制就是說:發送消息前,開啓事務(channel.txSelect()),而後發送消息,若是發送過程當中出現什麼異常,事務就會回滾(channel.txRollback()),若是發送成功則提交事務(channel.txCommit())。然而,這種方式有個缺點:吞吐量降低;

confirm模式用的居多:一旦channel進入confirm模式,全部在該信道上發佈的消息都將會被指派一個惟一的ID(從1開始),一旦消息被投遞到全部匹配的隊列以後;

rabbitMQ就會發送一個ACK給生產者(包含消息的惟一ID),這就使得生產者知道消息已經正確到達目的隊列了;

若是rabbitMQ沒能處理該消息,則會發送一個Nack消息給你,你能夠進行重試操做。

消息隊列丟數據:消息持久化。

處理消息隊列丟數據的狀況,通常是開啓持久化磁盤的配置。

這個持久化配置能夠和confirm機制配合使用,你能夠在消息持久化磁盤後,再給生產者發送一個Ack信號。

這樣,若是消息持久化磁盤以前,rabbitMQ陣亡了,那麼生產者收不到Ack信號,生產者會自動重發。

那麼如何持久化呢?

這裏順便說一下吧,其實也很容易,就下面兩步

將queue的持久化標識durable設置爲true,則表明是一個持久的隊列
發送消息的時候將deliveryMode=2
這樣設置之後,即便rabbitMQ掛了,重啓後也能恢復數據

消費者丟失消息:消費者丟數據通常是由於採用了自動確認消息模式,改成手動確認消息便可!

消費者在收到消息以後,處理消息以前,會自動回覆RabbitMQ已收到消息;

若是這時處理消息失敗,就會丟失該消息;

解決方案:處理消息成功後,手動回覆確認消息。

爲何不該該對全部的 message 都使用持久化機制?

首先,必然致使性能的降低,由於寫磁盤比寫 RAM 慢的多,message 的吞吐量可能有 10 倍的差距。

其次,message 的持久化機制用在 RabbitMQ 的內置 cluster 方案時會出現「坑爹」問題。矛盾點在於,若 message 設置了 persistent 屬性,但 queue 未設置 durable 屬性,那麼當該 queue 的 owner node 出現異常後,在未重建該 queue 前,發往該 queue 的 message 將被 blackholed ;若 message 設置了 persistent 屬性,同時 queue 也設置了 durable 屬性,那麼當 queue 的 owner node 異常且沒法重啓的狀況下,則該 queue 沒法在其餘 node 上重建,只能等待其 owner node 重啓後,才能恢復該 queue 的使用,而在這段時間內發送給該 queue 的 message 將被 blackholed 。

因此,是否要對 message 進行持久化,須要綜合考慮性能須要,以及可能遇到的問題。若想達到 100,000 條/秒以上的消息吞吐量(單 RabbitMQ 服務器),則要麼使用其餘的方式來確保 message 的可靠 delivery ,要麼使用很是快速的存儲系統以支持全持久化(例如使用 SSD)。另一種處理原則是:僅對關鍵消息做持久化處理(根據業務重要程度),且應該保證關鍵消息的量不會致使性能瓶頸。

如何保證高可用的?RabbitMQ 的集羣

RabbitMQ 是比較有表明性的,由於是基於主從(非分佈式)作高可用性的,咱們就以 RabbitMQ 爲例子講解第一種 MQ 的高可用性怎麼實現。RabbitMQ 有三種模式:單機模式、普通集羣模式、鏡像集羣模式。

單機模式,就是 Demo 級別的,通常就是你本地啓動了玩玩兒的?,沒人生產用單機模式

普通集羣模式,意思就是在多臺機器上啓動多個 RabbitMQ 實例,每一個機器啓動一個。你建立的 queue,只會放在一個 RabbitMQ 實例上,可是每一個實例都同步 queue 的元數據(元數據能夠認爲是 queue 的一些配置信息,經過元數據,能夠找到 queue 所在實例)。你消費的時候,實際上若是鏈接到了另一個實例,那麼那個實例會從 queue 所在實例上拉取數據過來。這方案主要是提升吞吐量的,就是說讓集羣中多個節點來服務某個 queue 的讀寫操做。

鏡像集羣模式:這種模式,纔是所謂的 RabbitMQ 的高可用模式。跟普通集羣模式不同的是,在鏡像集羣模式下,你建立的 queue,不管元數據仍是 queue 裏的消息都會存在於多個實例上,就是說,每一個 RabbitMQ 節點都有這個 queue 的一個完整鏡像,包含 queue 的所有數據的意思。而後每次你寫消息到 queue 的時候,都會自動把消息同步到多個實例的 queue 上。RabbitMQ 有很好的管理控制檯,就是在後臺新增一個策略,這個策略是鏡像集羣模式的策略,指定的時候是能夠要求數據同步到全部節點的,也能夠要求同步到指定數量的節點,再次建立 queue 的時候,應用這個策略,就會自動將數據同步到其餘的節點上去了。這樣的話,好處在於,你任何一個機器宕機了,沒事兒,其它機器(節點)還包含了這個 queue 的完整數據,別的 consumer 均可以到其它節點上去消費數據。壞處在於,第一,這個性能開銷也太大了吧,消息須要同步到全部機器上,致使網絡帶寬壓力和消耗很重!RabbitMQ 一個 queue 的數據都是放在一個節點裏的,鏡像集羣下,也是每一個節點都放這個 queue 的完整數據。

如何解決消息隊列的延時以及過時失效問題?消息隊列滿了之後該怎麼處理?有幾百萬消息持續積壓幾小時,說說怎麼解決?

消息積壓處理辦法:臨時緊急擴容:

先修復 consumer 的問題,確保其恢復消費速度,而後將現有 cnosumer 都停掉。
新建一個 topic,partition 是原來的 10 倍,臨時創建好原先 10 倍的 queue 數量。
而後寫一個臨時的分發數據的 consumer 程序,這個程序部署上去消費積壓的數據,消費以後不作耗時的處理,直接均勻輪詢寫入臨時創建好的 10 倍數量的 queue。
接着臨時徵用 10 倍的機器來部署 consumer,每一批 consumer 消費一個臨時 queue 的數據。這種作法至關因而臨時將 queue 資源和 consumer 資源擴大 10 倍,以正常的 10 倍速度來消費數據。
等快速消費完積壓數據以後,得恢復原先部署的架構,從新用原先的 consumer 機器來消費消息。
MQ中消息失效:假設你用的是 RabbitMQ,RabbtiMQ 是能夠設置過時時間的,也就是 TTL。若是消息在 queue 中積壓超過必定的時間就會被 RabbitMQ 給清理掉,這個數據就沒了。那這就是第二個坑了。這就不是說數據會大量積壓在 mq 裏,而是大量的數據會直接搞丟。咱們能夠採起一個方案,就是批量重導,這個咱們以前線上也有相似的場景幹過。就是大量積壓的時候,咱們當時就直接丟棄數據了,而後等過了高峯期之後,好比你們一塊兒喝咖啡熬夜到晚上12點之後,用戶都睡覺了。這個時候咱們就開始寫程序,將丟失的那批數據,寫個臨時程序,一點一點的查出來,而後從新灌入 mq 裏面去,把白天丟的數據給他補回來。也只能是這樣了。假設 1 萬個訂單積壓在 mq 裏面,沒有處理,其中 1000 個訂單都丟了,你只能手動寫程序把那 1000 個訂單給查出來,手動發到 mq 裏去再補一次。

mq消息隊列塊滿了:若是消息積壓在 mq 裏,你很長時間都沒有處理掉,此時致使 mq 都快寫滿了,咋辦?這個還有別的辦法嗎?沒有,誰讓你第一個方案執行的太慢了,你臨時寫程序,接入數據來消費,消費一個丟棄一個,都不要了,快速消費掉全部的消息。而後走第二個方案,到了晚上再補數據吧。

設計MQ思路

好比說這個消息隊列系統,咱們從如下幾個角度來考慮一下:

首先這個 mq 得支持可伸縮性吧,就是須要的時候快速擴容,就能夠增長吞吐量和容量,那怎麼搞?設計個分佈式的系統唄,參照一下 kafka 的設計理念,broker -> topic -> partition,每一個 partition 放一個機器,就存一部分數據。若是如今資源不夠了,簡單啊,給 topic 增長 partition,而後作數據遷移,增長機器,不就能夠存放更多數據,提供更高的吞吐量了?

其次你得考慮一下這個 mq 的數據要不要落地磁盤吧?那確定要了,落磁盤才能保證別進程掛了數據就丟了。那落磁盤的時候怎麼落啊?順序寫,這樣就沒有磁盤隨機讀寫的尋址開銷,磁盤順序讀寫的性能是很高的,這就是 kafka 的思路。

其次你考慮一下你的 mq 的可用性啊?這個事兒,具體參考以前可用性那個環節講解的 kafka 的高可用保障機制。多副本 -> leader & follower -> broker 掛了從新選舉 leader 便可對外服務。

能不能支持數據 0 丟失啊?能夠的,參考咱們以前說的那個 kafka 數據零丟失方案。

歡迎小夥伴留言評論。若有幫助,歡迎點贊+轉發分享。

歡迎你們關注民工哥的公衆號:民工哥技術之路
image.png

相關文章
相關標籤/搜索