Java面試官:我們簡單聊聊消息隊列

Java面試官:我們簡單聊聊消息隊列

項目中最常用的消息隊列是哪種? (單選)
0人
0%
A.Kafka
0人
0%
B.ActiveMQ
0人
0%
C.RabbitMQ
0人
0%
D.RocketMQ
<button>投票/<button>

都 2020 年,應該沒有項目不用消息隊列的吧?消息隊列解決了哪些問題,條件反射應該都能回答“異步消息”、“應用解耦”和“流量削峰”和。

消息隊列使用場景

1、異步處理

比如 之前做的基金項目,當用戶購買成功後,有如下幾個操作:

① 保存訂單信息;② 短信通知用戶;③ 當購買金額大的時候郵件通知銷售人員;④ 用戶積分增加,可兌換獎品或者優惠券。

同步處理這些請求,用戶體驗差。當我們對接口的 Rt(ResponseTime 響應時間)有要求時,需要異步處理比如短信、郵件和積分問題。

2、應用解耦

比如線下活動購物 POS 機消費,如果消費滿足一定條件,就進行微信推送引導用戶參與抽獎。當多部門協助時,其他部門負責 POS 機消費信息推送,本部門負責接收信息處理相應的業務邏輯。

3、流量削鋒

一般在秒殺或團搶活動中使用廣泛。用戶的請求,服務器接收後,首先寫入消息隊列。假如消息隊列長度超過最大數量,則直接拋棄用戶請求或跳轉到錯誤頁面。秒殺業務根據消息隊列中的請求信息,再做後續處理。

MQ 選型

面試中,考官經常會問你技術選型的問題,比如消息中間件,市場上種類繁多,如何選擇一個合適的呢?

諮詢了很多開發小夥伴,有的用 kafka、有的用 rocketMQ、還有的用 rabbitMQ。沒有好壞之分,只有適不適合。

Java面試官:我們簡單聊聊消息隊列

圖 1

根據圖 1 中,我們可以綜合幾個方面來選型:

① 社區活躍性。

萬一哪天這個 mq 社區沒人維護,出現 bug, 怎麼辦,重新再選一個 MQ 嗎?從圖中可以看出 ActiveMQ 活躍度很低。

② 單機吞吐量。

目前 ActiveMQ、RabbitMQ 吞吐量在萬級,而 RocketMQ 和 kafka 在 10 萬級;

③ 時效性

ActiveMQ、RocketMQ 和 kafka 延遲在 ms 級別,RabbitMQ 延遲在 ms 級別;

④ 可用性

ActiveMQ、RabbitMQ 基於主從複製,高可用; RocketMQ 和 kafka 非常高,分佈式架構;

⑤ 消息可靠性

RocketMQ 有較低概率丟失數據,RabbitMQ 基本不丟,RocketMQ 和 kafka 可以做到 0 丟失;

⑥ 功能擴展

kafka 功能較簡單,日誌採集 nb,其他是三個不分上下。

kafka

把消息放到【隊列】裡,我們叫【消息生產者】 producer,把 消息從隊列裡取出來,我們叫【消息消費者 】consumer。

1、consumer 如何區分 producer 裡的消息???

通常,我們在使用消息隊列時,n to n,多個 producer 和 consumer,如何進行區分,這裡使用了 topic 的概念,給 隊列取個響亮的名字。

2、kafka 如何保證吞吐量???

從上面圖 1 中我們看出,kafka 在 topic 從幾十到幾百個時,吞吐量會大幅度下降,儘量保證 topic 數量不要過多。

比如說:n 個 producer 往 topic 裡塞消息, n 個 consumer 從 topic 裡取消息。

為了提高吞吐量,kafka 使用 partion 分區的概念(和 Mysql 分區類似)

3、kafka 如何保證高可用

當然是集群了,用它,用它,用它。

在 kafka 集群中,我們把每個 kafka 服務器叫“broker”。

比如說我們這 3 臺 broker,每臺裡有 3 個 partion,當 producer 生產消息時,分別進入 3 臺 broker 的一個分區中(作為主分區),每臺 broker 裡剩餘的 2 個 partion 只做備份 其他 2 個 broker 裡的消息(備份分區)。 你品,你品,你細品。當某個 broker 掛了,選舉其他 broker 裡的 partion 來做主分區,實現高可用。

4、消費者如何保證消費消息

假設多個消費者 consumer 組團去消費分區裡的消息,一個 consumer 對應 一個 分區,假設有一個 consumer 掛了,必然另一個 consumer 要去接盤,但是我得知道掛掉的 consumer 消費進度。

kafka 在這裡使用了 offset 的概念,在以前版本的 Kafka,這個 offset 是由 Zookeeper 來管理的,後來 Kafka 開發者認為 Zookeeper 不合適大量的刪改操作,於是把 offset 在 broker 以內部 topic (__consumer_offsets) 的方式來保存起來。

消息隊列引發的問題

1、如何保證消息的冪等性???

① 數據庫層面使用唯一性索引;

② 每次先查再保存到數據庫;

2、如何保證消息的可靠性傳輸???

集群

3、如何保證消息的順序性???

生產者在寫的時候,其實可以指定一個 key,比如說我們指定了某個訂單 id 作為 key,那麼這個訂單相關的數據,一定會被分發到同一個 partition 中去,而且這個 partition 中的數據一定是有順序的。

寫 N 個內存 queue,具有相同 key 的數據都到同一個內存 queue;然後對於 N 個線程,每個線程分別消費一個內存 queue 即可,這樣就能保證順序性。

Java面試官:我們簡單聊聊消息隊列

| 文


分享到:


相關文章: