消息隊列面試題、RabbitMQ面試題、Kafka面試題、RocketMQ面試題 (史上最全、持續更新、吐血推薦)


瘋狂創客圈 史上最強 面試題 系列
Java基礎
JVM面試題(史上最強、持續更新、吐血推薦) http://www.javashuo.com/article/p-vhnpdnhb-vd.html
Java基礎面試題(史上最全、持續更新、吐血推薦) https://www.cnblogs.com/crazymakercircle/p/14366081.html
死鎖面試題(史上最強、持續更新) http://www.javashuo.com/article/p-uyudvdol-vd.html
多線程、線程池、內置鎖 面試題 (史上最強、持續更新) http://www.javashuo.com/article/p-tecubweb-vd.html
JUC併發包與容器類 - 面試題(史上最強、持續更新) http://www.javashuo.com/article/p-xcyjkbgi-vd.html
SpringBoot - 面試題(史上最強、持續更新) http://www.javashuo.com/article/p-xjwdvxjl-vd.html
Linux面試題(史上最全、持續更新、吐血推薦) https://www.cnblogs.com/crazymakercircle/p/14366893.html
分佈式、高併發、設計模式、架構
Zookeeper 面試題(史上最強、持續更新) http://www.javashuo.com/article/p-fvxlillp-vd.html
Mysql 面試題(史上最強、持續更新) http://www.javashuo.com/article/p-xhmrgfwk-vd.html
Redis 面試題 - 收藏版(史上最強、持續更新) http://www.javashuo.com/article/p-vkywkhov-vd.html
SpringCloud 面試題 - 收藏版(史上最強、持續更新) http://www.javashuo.com/article/p-pptrkvmu-vd.html
Netty 面試題 (史上最強、持續更新) http://www.javashuo.com/article/p-guuqkocg-vd.html
消息隊列、RabbitMQ、Kafka、RocketMQ面試題 (史上最全、持續更新、吐血推薦) https://www.cnblogs.com/crazymakercircle/p/14367425.html
設計模式面試題 (史上最全、持續更新、吐血推薦) http://www.javashuo.com/article/p-qnkzhtsu-vd.html
架構設計面試題 (史上最全、持續更新、吐血推薦) http://www.javashuo.com/article/p-dlpjqbmg-vd.html

MQ基礎

問:爲何使用MQ?MQ的優勢

簡答html

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

詳答java

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

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

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

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

削峯:減小高峯時期對服務器壓力。算法

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

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

缺點有如下幾個:數據庫

系統可用性下降apache

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

系統複雜度提升

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

一致性問題

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 有什麼優缺點?

ActiveMQ RabbitMQ RocketMQ Kafka ZeroMQ
單機吞吐量 比RabbitMQ低 2.6w/s(消息作持久化) 11.6w/s 17.3w/s 29w/s
開發語言 Java Erlang Java Scala/Java C
主要維護者 Apache Mozilla/Spring Alibaba Apache iMatix,創始人已去世
成熟度 成熟 成熟 開源版本不夠成熟 比較成熟 只有C、PHP等版本成熟
訂閱形式 點對點(p2p)、廣播(發佈-訂閱) 提供了4種:direct, topic ,Headers和fanout。fanout就是廣播模式 基於topic/messageTag以及按照消息類型、屬性進行正則匹配的發佈訂閱模式 基於topic以及按照topic進行正則匹配的發佈訂閱模式 點對點(p2p)
持久化 支持少許堆積 支持少許堆積 支持大量堆積 支持大量堆積 不支持
順序消息 不支持 不支持 支持 支持 不支持
性能穩定性 通常 較差 很好
集羣方式 支持簡單集羣模式,好比’主-備’,對高級集羣模式支持很差。 支持簡單集羣,'複製’模式,對高級集羣模式支持很差。 經常使用 多對’Master-Slave’ 模式,開源版本需手動切換Slave變成Master 自然的‘Leader-Slave’無狀態集羣,每臺服務器既是Master也是Slave 不支持
管理界面 通常 較好 通常

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

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

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

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

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

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

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

MQ 的常見問題有:

  1. 消息的順序問題
  2. 消息的重複問題

消息的順序問題

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

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

img

解決方案:

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

img

缺陷:

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

消息的重複問題

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

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

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

問:說說設計MQ思路?

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

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

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

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

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

RabbitMQ

問:什麼是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信號,生產者會自動重發。

那麼如何持久化呢?

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

  1. 將queue的持久化標識durable設置爲true,則表明是一個持久的隊列
  2. 發送消息的時候將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 都快寫滿了,咋辦?這個還有別的辦法嗎?沒有,誰讓你第一個方案執行的太慢了,你臨時寫程序,接入數據來消費,消費一個丟棄一個,都不要了,快速消費掉全部的消息。而後走第二個方案,到了晚上再補數據吧。

Kafka

基礎題

問:一、Apache Kafka 是什麼?

Apach Kafka 是一款分佈式流處理框架,用於實時構建流處理應用。它有一個核心 的功能廣爲人知,即做爲企業級的消息引擎被普遍使用。

你必定要先明確它的流處理框架地位,這樣能給面試官留 下一個很專業的印象。

問:二、什麼是消費者組?

消費者組是 Kafka 獨有的概念,若是面試官問這 個,就說明他對此是有必定了解的。我先給出標準答案:
一、定義:即消費者組是 Kafka 提供的可擴展且具備容錯性的消費者機制。
二、原理:在 Kafka 中,消費者組是一個由多個消費者實例 構成的組。多個實例共同訂閱若干個主題,實現共同消費。同一個組下的每一個實例都配置有 相同的組 ID,被分配不一樣的訂閱分區。當某個實例掛掉的時候,其餘實例會自動地承擔起 它負責消費的分區。

此時,又有一個小技巧給到你:消費者組的題目,可以幫你在某種程度上掌控下面的面試方
向。

  • 若是你擅長位移值原理,就不妨再提一下消費者組的位移提交機制;
  • 若是你擅長 Kafka Broker,能夠提一下消費者組與 Broker 之間的交互;
  • 若是你擅長與消費者組徹底不相關的 Producer,那麼就能夠這麼說:「消費者組要消 費的數據徹底來自於 Producer 端生產的消息,我對 Producer 仍是比較熟悉的。」

問:三、在 Kafka 中,ZooKeeper 的做用是什麼?

這是一道可以幫助你脫穎而出的題目。碰到這個題目,請在心中暗笑三聲。

目前,Kafka 使用 ZooKeeper 存放集羣元數據、成員管理、Controller 選舉,以及其餘一些管理類任務。以後,等 KIP-500 提案完成後,Kafka 將徹底再也不依賴 於 ZooKeeper。

記住,必定要突出「目前」,以彰顯你很是瞭解社區的演進計劃。「存放元數據」是指主題 分區的全部數據都保存在 ZooKeeper 中,且以它保存的數據爲權威,其餘「人」都要與它 保持對齊。「成員管理」是指 Broker 節點的註冊、註銷以及屬性變動,等 等。「Controller 選舉」是指選舉集羣 Controller,而其餘管理類任務包括但不限於主題 刪除、參數配置等。

不過,拋出 KIP-500 也多是個雙刃劍。碰到很是資深的面試官,他可能會進一步追問你 KIP-500 是作的。一言以蔽之:KIP-500 思想,是使用社區自研的基於 Raft 的共識算法, 替代 ZooKeeper,實現 Controller 自選舉

問:四、解釋下 Kafka 中位移(offset)的做用

在 Kafka 中,每一個 主題分區下的每條消息都被賦予了一個惟一的 ID 數值,用於標識它在分區中的位置。這個 ID 數值,就被稱爲位移,或者叫偏移量。一旦消息被寫入到分區日誌,它的位移值將不能 被修改。

答完這些以後,你還能夠把整個面試方向轉移到你但願的地方。常見方法有如下 3 種:

  1. 若是你深諳 Broker 底層日誌寫入的邏輯,能夠強調下消息在日誌中的存放格式;
  2. 若是你明白位移值一旦被肯定不能修改,能夠強調下「Log Cleaner 組件都不能影響位 移值」這件事情;
  3. 若是你對消費者的概念還算熟悉,能夠再詳細說說位移值和消費者位移值之間的區別。

問:五、闡述下 Kafka 中的領導者副本(Leader Replica)和追隨者副本 (Follower Replica)的區別

這道題表面上是考覈你對 Leader 和 Follower 區別的理解,但很容易引伸到 Kafka 的同步 機制上。所以,我建議你主動出擊,一次性地把隱含的考點也答出來,也許可以暫時把面試 官「唬住」,並體現你的專業性。

你能夠這麼回答:Kafka 副本當前分爲領導者副本和追隨者副本。只有 Leader 副本才能 對外提供讀寫服務,響應 Clients 端的請求。Follower 副本只是採用拉(PULL)的方 式,被動地同步 Leader 副本中的數據,而且在 Leader 副本所在的 Broker 宕機後,隨時 準備應聘 Leader 副本。

一般來講,回答到這個程度,其實才只說了 60%,所以,我建議你再回答兩個額外的加分 項。

  • 強調 Follower 副本也能對外提供讀服務。自 Kafka 2.4 版本開始,社區經過引入新的 Broker 端參數,容許 Follower 副本有限度地提供讀服務。
  • 強調 Leader 和 Follower 的消息序列在實際場景中不一致。不少緣由均可能形成 Leader 和 Follower 保存的消息序列不一致,好比程序 Bug、網絡問題等。這是很嚴重 的錯誤,必需要徹底規避。你能夠補充下,以前確保一致性的主要手段是高水位機制, 但高水位值沒法保證 Leader 連續變動場景下的數據一致性,所以,社區引入了 Leader Epoch 機制,來修復高水位值的弊端。關於「Leader Epoch 機制」,國內的資料不是 不少,它的普及度遠不如高水位,不妨大膽地把這個概念秀出來,力求驚豔一把。

問:六、如何設置 Kafka 能接收的最大消息的大小?

這道題除了要回答消費者端的參數設置以外,必定要加上 Broker 端的設置,這樣纔算完整。畢竟,若是 Producer 都不能向 Broker 端發送數據很大的消息,又何來消費一說呢? 所以,你須要同時設置 Broker 端參數和 Consumer 端參數。

  • Broker 端參數:message.max.bytes、max.message.bytes(主題級別)和 replica.fetch.max.bytes。
  • Consumer 端參數:fetch.message.max.bytes。

Broker 端的最後一個參數比較容易遺漏。咱們必須調整 Follower 副本可以接收的最大消 息的大小,不然,副本同步就會失敗。所以,把這個答出來的話,就是一個加分項。

問:七、監控 Kafka 的框架都有哪些?

面試官實際上是在 考察你對監控框架的瞭解廣度,或者說,你是否知道不少能監控 Kafka 的框架或方法。下 面這些就是 Kafka 發展歷程上比較有名氣的監控系統。

  1. Kafka Manager:應該算是最有名的專屬 Kafka 監控框架了,是獨立的監控系統。
  2. Kafka Monitor:LinkedIn 開源的免費框架,支持對集羣進行系統測試,並實時監控測
    試結果。
  3. CruiseControl:也是 LinkedIn 公司開源的監控框架,用於實時監測資源使用率,以及 提供經常使用運維操做等。無 UI 界面,只提供 REST API。
  4. JMX 監控:因爲 Kafka 提供的監控指標都是基於 JMX 的,所以,市面上任何可以集成 JMX 的框架均可以使用,好比 Zabbix 和 Prometheus。
  5. 已有大數據平臺本身的監控體系:像 Cloudera 提供的 CDH 這類大數據平臺,自然就提 供 Kafka 監控方案。
  6. JMXTool:社區提供的命令行工具,可以實時監控 JMX 指標。答上這一條,屬於絕對 的加分項,由於知道的人不多,並且會給人一種你對 Kafka 工具很是熟悉的感受。若是 你暫時不瞭解它的用法,能夠在命令行以無參數方式執行一下kafka-run-class.sh kafka.tools.JmxTool,學習下它的用法。

問:八、Broker 的 Heap Size 如何設置?

如何設置 Heap Size 的問題,其實和 Kafka 關係不大,它是一類很是通用的面試題目。一 旦你應對不當,面試方向頗有可能被引到 JVM 和 GC 上去,那樣的話,你被問住的概率就 會增大。所以,我建議你簡單地介紹一下 Heap Size 的設置方法,並把重點放在 Kafka Broker 堆大小設置的最佳實踐上。

好比,你能夠這樣回覆:任何 Java 進程 JVM 堆大小的設置都須要仔細地進行考量和測 試。一個常見的作法是,以默認的初始 JVM 堆大小運行程序,當系統達到穩定狀態後,手動觸發一次 Full GC,而後經過 JVM 工具查看 GC 後的存活對象大小。以後,將堆大小設 置成存活對象總大小的 1.5~2 倍。對於 Kafka 而言,這個方法也是適用的。不過,業界有 個最佳實踐,那就是將 Broker 的 Heap Size 固定爲 6GB。通過不少公司的驗證,這個大 小是足夠且良好的。

問:九、如何估算 Kafka 集羣的機器數量?

這道題目考查的是機器數量和所用資源之間的關聯關係。所謂資源,也就是 CPU、內存、磁盤和帶寬。

一般來講,CPU 和內存資源的充足是比較容易保證的,所以,你須要從磁盤空間和帶寬佔用兩個維度去評估機器數量。

在預估磁盤的佔用時,你必定不要忘記計算副本同步的開銷。若是一條消息佔用 1KB 的磁 盤空間,那麼,在有 3 個副本的主題中,你就須要 3KB 的總空間來保存這條消息。顯式地 將這些考慮因素答出來,可以彰顯你考慮問題的全面性,是一個可貴的加分項。

對於評估帶寬來講,常見的帶寬有 1Gbps 和 10Gbps,但你要切記,這兩個數字僅僅是最大值。所以,你最好和麪試官確認一下給定的帶寬是多少。而後,明確闡述出當帶寬佔用接 近總帶寬的 90% 時,丟包情形就會發生。這樣能顯示出你的網絡基本功。

問:十、Leader 老是 -1,怎麼破?

在生產環境中,你必定碰到過「某個主題分區不能工做了」的情形。使用命令行查看狀態的 話,會發現 Leader 是 -1,因而,你使用各類命令都無濟於事,最後只能用「重啓大 法」。

可是,有沒有什麼辦法,能夠不重啓集羣,就能解決此事呢?這就是此題的由來。

參考答案:刪除 ZooKeeper 節點 /controller,觸發 Controller 重選舉。 Controller 重選舉可以爲全部主題分區重刷分區狀態,能夠有效解決因不一致致使的 Leader 不可用問題。我幾乎能夠判定,當面試官問出此題時,要麼就是他真的不知道怎麼 解決在向你尋求答案,要麼他就是在等你說出這個答案。因此,千萬別一上來就說「來個重 啓」之類的話。

提升題

問:1.Kafka 的設計時什麼樣的呢?

Kafka 將消息以 topic 爲單位進行概括

將向 Kafka topic 發佈消息的程序成爲 producers.

將預訂 topics 並消費消息的程序成爲 consumer.

Kafka 以集羣的方式運行,能夠由一個或多個服務組成,每一個服務叫作一個 broker.

producers 經過網絡將消息發送到 Kafka 集羣,集羣向消費者提供消息

問:2.數據傳輸的事務定義有哪三種?

數據傳輸的事務定義一般有如下三種級別:

(1)最多一次: 消息不會被重複發送,最多被傳輸一次,但也有可能一次不傳輸

(2)最少一次: 消息不會被漏發送,最少被傳輸一次,但也有可能被重複傳輸.

(3)精確的一次(Exactly once): 不會漏傳輸也不會重複傳輸,每一個消息都傳輸被一次而

且僅僅被傳輸一次,這是你們所指望的

問:kafka事務。

分享一篇大佬講kafka事務的博客,這一篇講的更深刻:http://matt33.com/2018/11/04/kafka-transaction/

同時分享一下這兩篇博文,感受這篇博文講的更容易理解一些,面試我感受看這兩篇就夠了:https://www.jianshu.com/p/64c93065473e,https://www.cnblogs.com/middleware/p/9477133.html

Kafka從0.11版本開始引入了事務支持。事務能夠保證Kafka在Exactly Once語義的基礎上,生產和消費能夠跨分區和會話,要麼所有成功,要麼所有失敗。

1)Producer事務

爲了實現跨分區跨會話的事務,須要引入一個全局惟一的Transaction ID,並將Producer得到的PID和Transaction ID綁定。這樣當Producer重啓後就能夠經過正在進行的Transaction ID得到原來的PID。

爲了管理Transaction,Kafka引入了一個新的組件Transaction Coordinator。Producer就是經過和Transaction Coordinator交互得到Transaction ID對應的任務狀態。Transaction Coordinator還負責將事務全部寫入Kafka的一個內部Topic,這樣即便整個服務重啓,因爲事務狀態獲得保存,進行中的事務狀態能夠獲得恢復,從而繼續進行。

2)Consumer事務

上述事務機制主要是從Producer方面考慮,對於Consumer而言,事務的保證就會相對較弱,尤爲時沒法保證Commit的信息被精確消費。這是因爲Consumer能夠經過offset訪問任意信息,並且不一樣的Segment File生命週期不一樣,同一事務的消息可能會出現重啓後被刪除的狀況。

問:3.Kafka 判斷一個節點是否還活着有那兩個條件?

(1)節點必須能夠維護和 ZooKeeper 的鏈接,Zookeeper 經過心跳機制檢查每一個節點的連

(2)若是節點是個 follower,他必須能及時的同步 leader 的寫操做,延時不能過久

問:4.producer 是否直接將數據發送到 broker 的 leader(主節點)?

producer 直接將數據發送到 broker 的 leader(主節點),不須要在多個節點進行分發,爲了

幫助 producer 作到這點,全部的 Kafka 節點均可以及時的告知:哪些節點是活動的,目標

topic 目標分區的 leader 在哪。這樣 producer 就能夠直接將消息發送到目的地了

問:五、Kafa consumer 是否能夠消費指定分區消息?

Kafa consumer 消費消息時,向 broker 發出"fetch"請求去消費特定分區的消息,consumer

指定消息在日誌中的偏移量(offset),就能夠消費從這個位置開始的消息,customer 擁有

了 offset 的控制權,能夠向後回滾去從新消費以前的消息,這是頗有意義的

問:六、Kafka 消息是採用 Pull 模式,仍是 Push 模式?

Kafka 最初考慮的問題是,customer 應該從 brokes 拉取消息仍是 brokers 將消息推送到

consumer,也就是 pull 還 push。在這方面,Kafka 遵循了一種大部分消息系統共同的傳統

的設計:producer 將消息推送到 broker,consumer 從 broker 拉取消息

一些消息系統好比 Scribe 和 Apache Flume 採用了 push 模式,將消息推送到下游的

consumer。

這樣作有好處也有壞處:由 broker 決定消息推送的速率,對於不一樣消費速率的

consumer 就不太好處理了。消息系統都致力於讓 consumer 以最大的速率最快速的消費消

息,但不幸的是,push 模式下,當 broker 推送的速率遠大於 consumer 消費的速率時,

consumer 恐怕就要崩潰了。

最終, Kafka 仍是選取了傳統的 pull 模式。

Pull 模式的另一個好處是 consumer 能夠自主決定是否批量的從 broker 拉取數據。Push

模式必須在不知道下游 consumer 消費能力和消費策略的狀況下決定是當即推送每條消息還

是緩存以後批量推送。若是爲了不 consumer 崩潰而採用較低的推送速率,將可能致使一

次只推送較少的消息而形成浪費。Pull 模式下,consumer 就能夠根據本身的消費能力去決

定這些策略

Pull 有個缺點是,若是 broker 沒有可供消費的消息,將致使 consumer 不斷在循環中輪詢,

直到新消息到 t 達。爲了不這點,Kafka 有個參數可讓 consumer 阻塞知道新消息到達

(固然也能夠阻塞知道消息的數量達到某個特定的量這樣就能夠批量Pull)

問:7.Kafka 存儲在硬盤上的消息格式是什麼?

消息由一個固定長度的頭部和可變長度的字節數組組成。頭部包含了一個版本號和 CRC32

校驗碼。

消息長度: 4 bytes (value: 1+4+n)

版本號: 1 byte

CRC 校驗碼: 4 bytes

具體的消息: n bytes

問:8.Kafka 高效文件存儲設計特色:

(1).Kafka 把 topic 中一個 parition 大文件分紅多個小文件段,經過多個小文件段,就容易定

期清除或刪除已經消費完文件,減小磁盤佔用。

(2).經過索引信息能夠快速定位 message 和肯定 response 的最大大小。

(3).經過 index 元數據所有映射到 memory,能夠避免 segment file 的 IO 磁盤操做。

(4).經過索引文件稀疏存儲,能夠大幅下降 index 文件元數據佔用空間大小。

問:9.Kafka 與傳統消息系統之間有三個關鍵區別

(1).Kafka 持久化日誌,這些日誌能夠被重複讀取和無限期保留

(2).Kafka 是一個分佈式系統:它以集羣的方式運行,能夠靈活伸縮,在內部經過複製數據

提高容錯能力和高可用性

(3).Kafka 支持實時的流式處理

10.Kafka 建立 Topic 時如何將分區放置到不一樣的 Broker 中

副本因子不能大於 Broker 的個數;

第一個分區(編號爲 0)的第一個副本放置位置是隨機從 brokerList 選擇的;

其餘分區的第一個副本放置位置相對於第 0 個分區依次日後移。也就是若是咱們有 5 個

Broker,5 個分區,假設第一個分區放在第四個 Broker 上,那麼第二個分區將會放在第五

個 Broker 上;第三個分區將會放在第一個 Broker 上;第四個分區將會放在第二個

Broker 上,依次類推;

剩餘的副本相對於第一個副本放置位置實際上是由 nextReplicaShift 決定的,而這個數也是

隨機產生的

問:11.Kafka 新建的分區會在哪一個目錄下建立

在啓動 Kafka 集羣以前,咱們須要配置好 log.dirs 參數,其值是 Kafka 數據的存放目錄,

這個參數能夠配置多個目錄,目錄之間使用逗號分隔,一般這些目錄是分佈在不一樣的磁盤

上用於提升讀寫性能。

固然咱們也能夠配置 log.dir 參數,含義同樣。只須要設置其中一個便可。

若是 log.dirs 參數只配置了一個目錄,那麼分配到各個 Broker 上的分區確定只能在這個

目錄下建立文件夾用於存放數據。

可是若是 log.dirs 參數配置了多個目錄,那麼 Kafka 會在哪一個文件夾中建立分區目錄呢?

答案是:Kafka 會在含有分區目錄最少的文件夾中建立新的分區目錄,分區目錄名爲 Topic

名+分區 ID。注意,是分區文件夾總數最少的目錄,而不是磁盤使用量最少的目錄!也就

是說,若是你給 log.dirs 參數新增了一個新的磁盤,新的分區目錄確定是先在這個新的磁

盤上建立直到這個新的磁盤目錄擁有的分區目錄不是最少爲止。

問:12.partition 的數據如何保存到硬盤

topic 中的多個 partition 以文件夾的形式保存到 broker,每一個分區序號從 0 遞增,

且消息有序

Partition 文件下有多個 segment(xxx.index,xxx.log)

segment 文件裏的 大小和配置文件大小一致能夠根據要求修改 默認爲 1g

若是大小大於 1g 時,會滾動一個新的 segment 而且以上一個 segment 最後一條消息的偏移

量命名

問:13.kafka 的 ack 機制

request.required.acks 有三個值 0 1 -1

0:生產者不會等待 broker 的 ack,這個延遲最低可是存儲的保證最弱當 server 掛掉的時候

就會丟數據

1:服務端會等待 ack 值 leader 副本確認接收到消息後發送 ack 可是若是 leader 掛掉後他

不確保是否複製完成新 leader 也會致使數據丟失

-1:一樣在 1 的基礎上 服務端會等全部的 follower 的副本受到數據後纔會受到 leader 發出

的 ack,這樣數據不會丟失

問:14.Kafka 的消費者如何消費數據

消費者每次消費數據的時候,消費者都會記錄消費的物理偏移量(offset)的位置

等到下次消費時,他會接着上次位置繼續消費

問:15.消費者負載均衡策略

一個消費者組中的一個分片對應一個消費者成員,他能保證每一個消費者成員都能訪問,如

果組中成員太多會有空閒的成員

問:16.數據有序

一個消費者組裏它的內部是有序的

消費者組與消費者組之間是無序的

問:17.kafaka 生產數據時數據的分組策略

生產者決定數據產生到集羣的哪一個 partition 中

每一條消息都是以(key,value)格式

Key 是由生產者發送數據傳入

因此生產者(key)決定了數據產生到集羣的哪一個 partition

深度思考題

問:十一、LEO、LSO、AR、ISR、HW 都表示什麼含義?

  • LEO:Log End Offset。日誌末端位移值或末端偏移量,表示日誌下一條待插入消息的 位移值。舉個例子,若是日誌有 10 條消息,位移值從 0 開始,那麼,第 10 條消息的位 移值就是 9。此時,LEO = 10。
  • LSO:Log Stable Offset。這是 Kafka 事務的概念。若是你沒有使用到事務,那麼這個 值不存在(其實也不是不存在,只是設置成一個無心義的值)。該值控制了事務型消費 者可以看到的消息範圍。它常常與 Log Start Offset,即日誌起始位移值相混淆,由於 有些人將後者縮寫成 LSO,這是不對的。在 Kafka 中,LSO 就是指代 Log Stable Offset。
  • AR:Assigned Replicas。AR 是主題被建立後,分區建立時被分配的副本集合,副本個 數由副本因子決定。
  • ISR:In-Sync Replicas。Kafka 中特別重要的概念,指代的是 AR 中那些與 Leader 保 持同步的副本集合。在 AR 中的副本可能不在 ISR 中,但 Leader 副本自然就包含在 ISR 中。關於 ISR,還有一個常見的面試題目是如何判斷副本是否應該屬於 ISR。目前的判斷 依據是:Follower 副本的 LEO 落後 Leader LEO 的時間,是否超過了 Broker 端參數 replica.lag.time.max.ms 值。若是超過了,副本就會被從 ISR 中移除。
  • HW:高水位值(High watermark)。這是控制消費者可讀取消息範圍的重要字段。一 個普通消費者只能「看到」Leader 副本上介於 Log Start Offset 和 HW(不含)之間的 全部消息。水位以上的消息是對消費者不可見的。關於 HW,問法有不少,我能想到的 最高級的問法,就是讓你完整地梳理下 Follower 副本拉取 Leader 副本、執行同步機制 的詳細步驟。這就是咱們的第 20 道題的題目,一下子我會給出答案和解析。

問:十二、Kafka 能手動刪除消息嗎?

其實,Kafka 不須要用戶手動刪除消息。它自己提供了留存策略,可以自動刪除過時消息。 固然,它是支持手動刪除消息的。所以,你最好從這兩個維度去回答。

  • 對於設置了 Key 且參數 cleanup.policy=compact 的主題而言,咱們能夠構造一條 <Key,null> 的消息發送給 Broker,依靠 Log Cleaner 組件提供的功能刪除掉該 Key 的消息。
  • 對於普通主題而言,咱們能夠使用 kafka-delete-records 命令,或編寫程序調用 Admin.deleteRecords 方法來刪除消息。這兩種方法異曲同工,底層都是調用 Admin 的 deleteRecords 方法,經過將分區 Log Start Offset 值擡高的方式間接刪除消息。

問:1三、__consumer_offsets 是作什麼用的?

這是一個內部主題,公開的官網資料不多涉及到。所以,我認爲,此題屬於面試官炫技一類 的題目。你要當心這裏的考點:該主題有 3 個重要的知識點,你必定要所有答出來,纔會顯得對這塊知識很是熟悉。

它是一個內部主題,無需手動干預,由 Kafka 自行管理。固然,咱們能夠建立該主題。

它的主要做用是負責註冊消費者以及保存位移值。可能你對保存位移值的功能很熟悉, 但其實該主題也是保存消費者元數據的地方。千萬記得把這一點也回答上。另外,這裏 的消費者泛指消費者組和獨立消費者,而不只僅是消費者組。

Kafka 的 GroupCoordinator 組件提供對該主題完整的管理功能,包括該主題的建立、 寫入、讀取和 Leader 維護等。

問:1四、分區 Leader 選舉策略有幾種?

分區的 Leader 副本選舉對用戶是徹底透明的,它是由 Controller 獨立完成的。你須要回答的是,在哪些場景下,須要執行分區 Leader 選舉。每一種場景對應於一種選舉策略。當前,Kafka 有 4 種分區 Leader 選舉策略。

  • OfflinePartition Leader 選舉:每當有分區上線時,就須要執行 Leader 選舉。所謂的分區上線,多是建立了新分區,也多是以前的下線分區從新上線。這是最多見的分區 Leader 選舉場景。
  • ReassignPartition Leader 選舉:當你手動運行 kafka-reassign-partitions 命令,或者是調用 Admin 的 alterPartitionReassignments 方法執行分區副本重分配時,可能觸發此類選舉。假設原來的 AR 是[1,2,3],Leader 是 1,當執行副本重分配後,副本集 合 AR 被設置成[4,5,6],顯然,Leader 必需要變動,此時會發生 Reassign Partition Leader 選舉。
  • PreferredReplicaPartition Leader 選舉:當你手動運行 kafka-preferred-replica- election 命令,或自動觸發了 Preferred Leader 選舉時,該類策略被激活。所謂的 Preferred Leader,指的是 AR 中的第一個副本。好比 AR 是[3,2,1],那麼, Preferred Leader 就是 3。
  • ControlledShutdownPartition Leader 選舉:當 Broker 正常關閉時,該 Broker 上 的全部 Leader 副本都會下線,所以,須要爲受影響的分區執行相應的 Leader 選舉。

這 4 類選舉策略的大體思想是相似的,即從 AR 中挑選首個在 ISR 中的副本,做爲新 Leader。固然,個別策略有些微小差別。不過,回答到這種程度,應該足以應付面試官 了。畢竟,微小差異對選舉 Leader 這件事的影響很小。

問:Kafka中有那些地方須要選舉?這些地方的選舉策略又有哪些?

參考:http://www.javashuo.com/article/p-pkvcxbay-ra.html

控制器的選舉

  • Kafka Controller的選舉是依賴Zookeeper來實現的,在Kafka集羣中哪一個broker可以成功建立/controller這個臨時(EPHEMERAL)節點他就能夠成爲Kafka Controller。

分區leader的選舉

消費者相關的選舉

  • 組協調器GroupCoordinator須要爲消費組內的消費者選舉出一個消費組的leader,這個選舉的算法也很簡單,分兩種狀況分析。若是消費組內尚未leader,那麼第一個加入消費組的消費者即爲消費組的leader。若是某一時刻leader消費者因爲某些緣由退出了消費組,那麼會從新選舉一個新的leader。

問:1五、Kafka 的哪些場景中使用了零拷貝(Zero Copy)?

Zero Copy 是特別容易被問到的高階題目。在 Kafka 中,體現 Zero Copy 使用場景的地方有兩處:基於 mmap 的索引和日誌文件讀寫所用的 TransportLayer

先說第一個。索引都是基於 MappedByteBuffer 的,也就是讓用戶態和內核態共享內核態 的數據緩衝區,此時,數據不須要複製到用戶態空間。不過,mmap 雖然避免了沒必要要的 拷貝,但不必定就能保證很高的性能。在不一樣的操做系統下,mmap 的建立和銷燬成本可 能是不同的。很高的建立和銷燬開銷會抵消 Zero Copy 帶來的性能優點。因爲這種不確 定性,在 Kafka 中,只有索引應用了 mmap,最核心的日誌並未使用 mmap 機制。

再說第二個。TransportLayer 是 Kafka 傳輸層的接口。它的某個實現類使用了 FileChannel 的 transferTo 方法。該方法底層使用 sendfile 實現了 Zero Copy。對 Kafka 而言,若是 I/O 通道使用普通的 PLAINTEXT,那麼,Kafka 就能夠利用 Zero Copy 特 性,直接將頁緩存中的數據發送到網卡的 Buffer 中,避免中間的屢次拷貝。相反,若是 I/O 通道啓用了 SSL,那麼,Kafka 便沒法利用 Zero Copy 特性了。

問:1六、Kafka 爲何不支持讀寫分離?

這道題目考察的是你對 Leader/Follower 模型的思考。

Leader/Follower 模型並無規定 Follower 副本不能夠對外提供讀服務。不少框架都是允 許這麼作的,只是 Kafka 最初爲了不不一致性的問題,而採用了讓 Leader 統一提供服 務的方式。

不過,在開始回答這道題時,你能夠率先亮出觀點:自 Kafka 2.4 以後,Kafka 提供了有限度的讀寫分離,也就是說,Follower 副本可以對外提供讀服務

說完這些以後,你能夠再給出以前的版本不支持讀寫分離的理由。

  • 場景不適用。讀寫分離適用於那種讀負載很大,而寫操做相對不頻繁的場景,可 Kafka 不屬於這樣的場景。
  • 同步機制。Kafka 採用 PULL 方式實現 Follower 的同步,所以,Follower 與 Leader 存 在不一致性窗口。若是容許讀 Follower 副本,就勢必要處理消息滯後(Lagging)的問題。

問:1七、如何調優 Kafka?

回答任何調優問題的第一步,就是肯定優化目標,而且定量給出目標!這點特別重要。對於 Kafka 而言,常見的優化目標是吞吐量、延時、持久性和可用性。每個方向的優化思路都 是不一樣的,甚至是相反的。

肯定了目標以後,還要明確優化的維度。有些調優屬於通用的優化思路,好比對操做系統、 JVM 等的優化;有些則是有針對性的,好比要優化 Kafka 的 TPS。咱們須要從 3 個方向去考慮

  • Producer 端:增長 batch.size、linger.ms,啓用壓縮,關閉重試等。
  • Broker 端:增長 num.replica.fetchers,提高 Follower 同步 TPS,避免 Broker Full GC 等。
  • Consumer:增長 fetch.min.bytes 等

問:1八、Controller 發生網絡分區(Network Partitioning)時,Kafka 會怎 麼樣?

這道題目可以誘發咱們對分佈式系統設計、CAP 理論、一致性等多方面的思考。不過,針 對故障定位和分析的這類問題,我建議你首先言明「實用至上」的觀點,即不論怎麼進行理論分析,永遠都要以實際結果爲準。一旦發生 Controller 網絡分區,那麼,第一要務就是 查看集羣是否出現「腦裂」,即同時出現兩個甚至是多個 Controller 組件。這能夠根據 Broker 端監控指標 ActiveControllerCount 來判斷。

如今,咱們分析下,一旦出現這種狀況,Kafka 會怎麼樣。

因爲 Controller 會給 Broker 發送 3 類請求,即LeaderAndIsrRequest、 StopReplicaRequest 和 UpdateMetadataRequest,所以,一旦出現網絡分區,這些請求將不能順利到達 Broker 端。這將影響主題的建立、修改、刪除操做的信息同步,表現爲 集羣彷彿僵住了同樣,沒法感知到後面的全部操做。所以,網絡分區一般都是很是嚴重的問 題,要趕快修復。

問:1九、Java Consumer 爲何採用單線程來獲取消息?

在回答以前,若是先把這句話說出來,必定會加分:Java Consumer 是雙線程的設計。一 個線程是用戶主線程,負責獲取消息;另外一個線程是心跳線程,負責向 Kafka 彙報消費者 存活狀況。將心跳單獨放入專屬的線程,可以有效地規避因消息處理速度慢而被視爲下線 的「假死」狀況。

單線程獲取消息的設計可以避免阻塞式的消息獲取方式。單線程輪詢方式容易實現異步非阻塞式,這樣便於將消費者擴展成支持實時流處理的操做算子。由於不少實時流處理操做算子都不能是阻塞式的。另一個可能的好處是,能夠簡化代碼的開發。多線程交互的代碼是很是容易出錯的。

問:20、簡述 Follower 副本消息同步的完整流程

首先,Follower 發送 FETCH 請求給 Leader。接着,Leader 會讀取底層日誌文件中的消 息數據,再更新它內存中的 Follower 副本的 LEO 值,更新爲 FETCH 請求中的 fetchOffset 值。最後,嘗試更新分區高水位值。Follower 接收到 FETCH 響應以後,會把 消息寫入到底層日誌,接着更新 LEO 和 HW 值。

Leader 和 Follower 的 HW 值更新時機是不一樣的,Follower 的 HW 更新永遠落後於 Leader 的 HW。這種時間上的錯配是形成各類不一致的緣由。

重點:kafka如何實現高吞吐?

問:一、簡單說說:kafka如何實現高吞吐?

Kafka是分佈式消息系統,須要處理海量的消息,Kafka的設計是把全部的消息都寫入速度低容量大的硬盤,以此來換取更強的存儲能力,但實際上,使用硬盤並無帶來過多的性能損失。kafka主要使用瞭如下幾個方式實現了超高的吞吐率:

    • 順序讀寫;

    • 零拷貝

    • 文件分段

    • 批量發送

    • 數據壓縮。

具體來講:

讀寫文件依賴OS文件系統的頁緩存,而不是在JVM內部緩存數據,利用OS來緩存,內存利用率高

sendfile技術(零拷貝),避免了傳統網絡IO四步流程

支持End-to-End的壓縮

順序IO以及常量時間get、put消息

Partition 能夠很好的橫向擴展和提供高併發處理

問:2 Kafka如何實現每秒上百萬的超高併發寫入?掌握好面試給你打滿分

Kafka 是高吞吐低延遲的高併發、高性能的消息中間件,在大數據領域有極爲普遍的運用。配置良好的 Kafka 集羣甚至能夠作到每秒幾十萬、上百萬的超高併發寫入。

頁緩存技術 + 磁盤順序寫

首先 Kafka 每次接收到數據都會往磁盤上去寫,以下圖所示:

加粗樣式

那麼在這裏咱們不由有一個疑問了,若是把數據基於磁盤來存儲,頻繁的往磁盤文件裏寫數據,這個性能會不會不好?你們確定都以爲磁盤寫性能是極差的。

沒錯,要是真的跟上面那個圖那麼簡單的話,那確實這個性能是比較差的。

可是實際上 Kafka 在這裏有極爲優秀和出色的設計,就是爲了保證數據寫入性能,首先 Kafka 是基於操做系統的頁緩存來實現文件寫入的。

操做系統自己有一層緩存,叫作 Page Cache,是在內存裏的緩存,咱們也能夠稱之爲 OS Cache,意思就是操做系統本身管理的緩存。

你在寫入磁盤文件的時候,能夠直接寫入這個 OS Cache 裏,也就是僅僅寫入內存中,接下來由操做系統本身決定何時把 OS Cache 裏的數據真的刷入磁盤文件中。

僅僅這一個步驟,就能夠將磁盤文件寫性能提高不少了,由於其實這裏至關因而在寫內存,不是在寫磁盤,你們看下圖:

在這裏插入圖片描述

接着另一個就是 kafka 寫數據的時候,很是關鍵的一點,它是以磁盤順序寫的方式來寫的。

也就是說,僅僅將數據追加到文件的末尾,不是在文件的隨機位置來修改數據。

普通的機械磁盤若是你要是隨機寫的話,確實性能極差,也就是隨便找到文件的某個位置來寫數據。

可是若是你是追加文件末尾按照順序的方式來寫數據的話,那麼這種磁盤順序寫的性能基本上能夠跟寫內存的性能自己也是差很少的。

因此你們就知道了,上面那個圖裏,Kafka 在寫數據的時候,一方面基於 OS 層面的 Page Cache 來寫數據,因此性能很高,本質就是在寫內存罷了。

另一個,它是採用磁盤順序寫的方式,因此即便數據刷入磁盤的時候,性能也是極高的,也跟寫內存是差很少的。

基於上面兩點,Kafka 就實現了寫入數據的超高性能。那麼你們想一想,假如說 Kafka 寫入一條數據要耗費 1 毫秒的時間,那麼是否是每秒就是能夠寫入 1000 條數據?

可是假如 Kafka 的性能極高,寫入一條數據僅僅耗費 0.01 毫秒呢?那麼每秒是否是就能夠寫入 10 萬條數據?

因此要保證每秒寫入幾萬甚至幾十萬條數據的核心點,就是盡最大可能提高每條數據寫入的性能,這樣就能夠在單位時間內寫入更多的數據量,提高吞吐量。

零拷貝技術

說完了寫入這塊,再來談談消費這塊。

你們應該都知道,從 Kafka 裏咱們常常要消費數據,那麼消費的時候實際上就是要從 Kafka 的磁盤文件裏讀取某條數據而後發送給下游的消費者,以下圖所示:

在這裏插入圖片描述

那麼這裏若是頻繁的從磁盤讀數據而後發給消費者,性能瓶頸在哪裏呢?

假設要是 Kafka 什麼優化都不作,就是很簡單的從磁盤讀數據發送給下游的消費者,那麼大概過程以下所示:

先看看要讀的數據在不在 OS Cache 裏,若是不在的話就從磁盤文件裏讀取數據後放入 OS Cache。

接着從操做系統的 OS Cache 裏拷貝數據到應用程序進程的緩存裏,再從應用程序進程的緩存裏拷貝數據到操做系統層面的 Socket 緩存裏。

最後從 Socket 緩存裏提取數據後發送到網卡,最後發送出去給下游消費。

整個過程,以下圖所示:

在這裏插入圖片描述

你們看上圖,很明顯能夠看到有兩次不必的拷貝吧!一次是從操做系統的 Cache 裏拷貝到應用進程的緩存裏,接着又從應用程序緩存裏拷貝回操做系統的 Socket 緩存裏。

並且爲了進行這兩次拷貝,中間還發生了好幾回上下文切換,一下子是應用程序在執行,一下子上下文切換到操做系統來執行。

因此這種方式來讀取數據是比較消耗性能的。Kafka 爲了解決這個問題,在讀數據的時候是引入零拷貝技術。

也就是說,直接讓操做系統的 Cache 中的數據發送到網卡後傳輸給下游的消費者,中間跳過了兩次拷貝數據的步驟,Socket 緩存中僅僅會拷貝一個描述符過去,不會拷貝數據到 Socket 緩存。

你們看下圖,體會一下這個精妙的過程:

在這裏插入圖片描述

經過零拷貝技術,就不須要把 OS Cache 裏的數據拷貝到應用緩存,再從應用緩存拷貝到 Socket 緩存了,兩次拷貝都省略了,因此叫作零拷貝。

對 Socket 緩存僅僅就是拷貝數據的描述符過去,而後數據就直接從 OS Cache 中發送到網卡上去了,這個過程大大的提高了數據消費時讀取文件數據的性能。

並且你們會注意到,在從磁盤讀數據的時候,會先看看 OS Cache 內存中是否有,若是有的話,其實讀數據都是直接讀內存的。

若是 Kafka 集羣通過良好的調優,你們會發現大量的數據都是直接寫入 OS Cache 中,而後讀數據的時候也是從 OS Cache 中讀。

至關因而 Kafka 徹底基於內存提供數據的寫和讀了,因此這個總體性能會極其的高。

RocketMQ

問:多個MQ如何選型?

RabbitMQ
erlang開發,對消息堆積的支持並很差,當大量消息積壓的時候,會致使 RabbitMQ 的性能急劇降低。每秒鐘能夠處理幾萬到十幾萬條消息。

RocketMQ
java開發,面向互聯網集羣化,功能豐富,對在線業務的響應時延作了不少的優化,大多數狀況下能夠作到毫秒級的響應,每秒鐘大概能處理幾十萬條消息。

Kafka
Scala開發,面向日誌,功能豐富,性能最高。當你的業務場景中,每秒鐘消息數量沒有那麼多的時候,Kafka 的時延反而會比較高。因此,Kafka 不太適合在線業務場景。

ActiveMQ
java開發,簡單,穩定,性能不如前面三個。不推薦。

基礎題

問:RocketMQ組成部分(角色)有哪些?

Nameserver
無狀態,動態列表;這也是和zookeeper的重要區別之一。zookeeper是有狀態的。

Producer
消息生產者,負責發消息到Broker。

Broker
就是MQ自己,負責收發消息、持久化消息等。

Consumer
消息消費者,負責從Broker上拉取消息進行消費,消費完進行ack。

問:RocketMQ消費模式有幾種?

集羣消費

  • 一條消息只會被同Group中的一個Consumer消費
  • 多個Group同時消費一個Topic時,每一個Group都會有一個Consumer消費到數據

廣播消費

  • 消息將對一個Consumer Group 下的各個 Consumer 實例都消費一遍。即即便這些 Consumer 屬於同一個Consumer Group ,消息也會被 Consumer Group 中的每一個 Consumer 都消費一次。

問:消息重複消費如何解決?

出現緣由
正常狀況下在consumer真正消費完消息後應該發送ack,通知broker該消息已正常消費,從queue中剔除
當ack由於網絡緣由沒法發送到broker,broker會認爲詞條消息沒有被消費,此後會開啓消息重投機制把消息再次投遞到consumer。

消費模式:在CLUSTERING模式下,消息在broker中會保證相同group的consumer消費一次,可是針對不一樣group的consumer會推送屢次

解決方案

  • 數據庫表:處理消息前,使用消息主鍵在表中帶有約束的字段中insert
  • Map:單機時能夠使用map作限制,消費時查詢當前消息id是否是已經存在
  • Redis:使用分佈式鎖。

問:RocketMQ如何保證消息的順序消費?

首先多個queue只能保證單個queue裏的順序,queue是典型的FIFO,自然順序。多個queue同時消費是沒法絕對保證消息的有序性的。
能夠使用同一topic,同一個QUEUE,發消息的時候一個線程去發送消息,消費的時候 一個線程去消費一個queue裏的消息。

問:RocketMQ如何保證消息不丟失?

Producer端

採起send()同步發消息,發送結果是同步感知的。
發送失敗後能夠重試,設置重試次數。默認3次。

Broker端
修改刷盤策略爲同步刷盤。默認狀況下是異步刷盤的。
集羣部署

Consumer端
徹底消費正常後在進行手動ack確認

問:RocketMQ 由哪些角色組成?

生產者(Producer):負責產生消息,生產者向消息服務器發送由業務應用程序系統生成的消息。

消費者(Consumer):負責消費消息,消費者從消息服務器拉取信息並將其輸入用戶應用程序。

消息服務器(Broker):是消息存儲中心,主要做用是接收來自 Producer 的消息並存儲, Consumer 從這裏取得消息。

名稱服務器(NameServer):用來保存 Broker 相關 Topic 等元信息並給 Producer ,提供 Consumer 查找 Broker 信息。

問:RocketMQ執行流程

一、啓動 Namesrv,Namesrv起 來後監聽端口,等待 Broker、Producer、Consumer 連上來,至關於一個路由控制中心。

二、Broker 啓動,跟全部的 Namesrv 保持長鏈接,定時發送心跳包。

三、收發消息前,先建立 Topic 。建立 Topic 時,須要指定該 Topic 要存儲在 哪些 Broker上。也能夠在發送消息時自動建立Topic。

四、Producer 發送消息。

五、Consumer 消費消息。

問:請說說你對 Producer 的瞭解?

一、得到 Topic-Broker 的映射關係。

Producer 啓動時,也須要指定 Namesrv 的地址,從 Namesrv 集羣中選一臺創建長鏈接。

生產者每 30 秒從 Namesrv 獲取 Topic 跟 Broker 的映射關係,更新到本地內存中。而後再跟 Topic 涉及的全部 Broker 創建長鏈接,每隔 30 秒發一次心跳。

二、生產者端的負載均衡。

生產者發送時,會自動輪詢當前全部可發送的broker,一條消息發送成功,下次換另一個broker發送,以達到消息平均落到全部的broker上。

問:說說你對 Consumer 的瞭解?

一、得到 Topic-Broker 的映射關係。

Consumer 啓動時須要指定 Namesrv 地址,與其中一個 Namesrv 創建長鏈接。消費者每隔 30 秒從 Namesrv 獲取全部Topic 的最新隊列狀況,

Consumer 跟 Broker 是長鏈接,會每隔 30 秒發心跳信息到Broker .

二、消費者端的負載均衡。根據消費者的消費模式不一樣,負載均衡方式也不一樣。

問:消費者消費模式有幾種?

消費者消費模式有兩種:集羣消費和廣播消費。

  1. 集羣消費

消費者的一種消費模式。一個 Consumer Group 中的各個 Consumer 實例分攤去消費消息,即一條消息只會投遞到一個 Consumer Group 下面的一個實例。

  1. 廣播消費

消費者的一種消費模式。消息將對一 個Consumer Group 下的各個 Consumer 實例都投遞一遍。即即便這些 Consumer 屬於同一個Consumer Group ,消息也會被 Consumer Group 中的每一個 Consumer 都消費一次。

問:消費者獲取消息有幾種模式?

消費者獲取消息有兩種模式:推送模式和拉取模式。

  1. PushConsumer

推送模式(雖然 RocketMQ 使用的是長輪詢)的消費者。消息的能及時被消費。使用很是簡單,內部已處理如線程池消費、流控、負載均衡、異常處理等等的各類場景。

  1. PullConsumer

拉取模式的消費者。應用主動控制拉取的時機,怎麼拉取,怎麼消費等。主動權更高。但要本身處理各類場景。

問:什麼是定時消息?如何實現?

定時消息,是指消息發到 Broker 後,不能馬上被 Consumer 消費,要到特定的時間點或者等待特定的時間後才能被消費。

提升題

問:RocketMQ如何實現分佈式事務?

一、生產者向MQ服務器發送half消息。
二、half消息發送成功後,MQ服務器返回確認消息給生產者。
三、生產者開始執行本地事務。
四、根據本地事務執行的結果(UNKNOWcommitrollback)向MQ Server發送提交或回滾消息。
五、若是錯過了(可能由於網絡異常、生產者忽然宕機等致使的異常狀況)提交/回滾消息,則MQ服務器將向同一組中的每一個生產者發送回查消息以獲取事務狀態。
六、回查生產者本地事物狀態。
七、生產者根據本地事務狀態發送提交/回滾消息。
八、MQ服務器將丟棄回滾的消息,但已提交(進行過二次確認的half消息)的消息將投遞給消費者進行消費。

Half Message:預處理消息,當broker收到此類消息後,會存儲到RMQ_SYS_TRANS_HALF_TOPIC的消息消費隊列中

檢查事務狀態:Broker會開啓一個定時任務,消費RMQ_SYS_TRANS_HALF_TOPIC隊列中的消息,每次執行任務會向消息發送者確認事務執行狀態(提交、回滾、未知),若是是未知,Broker會定時去回調在從新檢查。

超時:若是超過回查次數,默認回滾消息。
也就是他並未真正進入Topic的queue,而是用了臨時queue來放所謂的half message,等提交事務後纔會真正的將half message轉移到topic下的queue。

問:RocketMQ的消息堆積如何處理?

一、若是能夠添加消費者解決,就添加消費者的數據量 二、若是出現了queue,可是消費者多的狀況。能夠使用準備一個臨時的topic,同時建立一些queue,在臨時建立一個消費者來把這些消息轉移到topic中,讓消費者消費。

相關文章
相關標籤/搜索