MQ消息隊列篇:三大MQ產品的必備面試種子題

来源:https://www.cnblogs.com/guoxiaoyu/archive/2023/08/01/17594613.html
-Advertisement-
Play Games

MQ(Message Queue)作為一種用於實現非同步通信的技術,具有重要的作用和應用場景。在面試過程中,MQ相關的問題經常被問到,因此瞭解MQ的用途和設計原則是必不可少的。本文總結了MQ的常見面試題,包括MQ的作用、產品選型、消息不丟失的保證、消息消費的冪等性、消息順序的保證、消息的高效讀寫、分佈... ...


MQ有什麼用?

MQ(消息隊列)是一種FIFO(先進先出)的數據結構,主要用於實現非同步通信、削峰平谷和解耦等功能。它通過將生產者生成的消息發送到隊列中,然後由消費者進行消費。這樣,生產者和消費者之間就不存在直接的耦合關係。

其中,MQ的優勢主要體現在以下幾個方面:

  • 非同步通信:由於存在MQ這個中間件,生產者將消息發送到隊列後,可以立即返回,無需等待消費者處理完畢。這樣可以提高系統的響應速度和併發能力。
  • 削峰平谷:當系統出現峰值請求時,MQ可以存儲大量的請求消息,將峰值數據緩衝下來,然後由消費者按照自己的處理能力逐步消費。這樣可以避免系統因突發流量而崩潰,提高系統的穩定性和可靠性。
  • 解耦功能:MQ可以將生產者和消費者兩端分離開來,實現系統之間的解耦。尤其在跨語言的場景下,MQ可以輕鬆實現不同語言程式之間的通信,簡化開發和維護的複雜性。

然而,引入MQ也存在一些劣勢需要註意:

  • 高可用性要求:為了保證MQ的正常運行,需要對MQ進行高可用性的設計和部署。一旦MQ宕機,整個業務流程可能會受到影響,導致系統不可用。
  • 系統複雜性提高:引入MQ後,需要專門的人員進行維護和管理,並對MQ產品有深入的瞭解。同時,為了保證消息的不丟失和消費冪等性,還需要進行一些額外的工作。
  • 系統一致性問題:由於MQ是非同步通信的方式,當一個業務生成後,如果需要兩個系統之間的一致性,就需要保證兩個系統都成功執行完成。否則,可能會出現數據不一致的情況。

綜上所述,MQ在提供非同步通信、削峰平谷和解耦等功能的同時,也需要註意高可用性、系統複雜性和系統一致性等問題。在使用MQ時,需要綜合考慮這些因素,併進行適當的設計和調優。

如何進行產品選型

目前市場上有三大主流MQ產品供選擇,它們分別是kafka、rabbitmq和rocketmq。

  • kafka的性能最快,效率最高,適用於處理日誌分析、大數據分析等場景。然而,kafka存在數據丟失的風險,並且功能相對單一,不保證消息的可靠性。
  • rabbitmq保證了消息的可靠性,但無法處理大數據量的消息隊列。一旦數據量增大,整個MQ伺服器的性能將下降。因此,rabbitmq適用於小規模場景。
  • rocketmq吸取了kafka和rabbitmq的優點,幾乎可以應用於各種場景。它既具有高效率又具有高可靠性。不過需要註意的是,開源版本的rocketmq可能不如商業版本穩定和可靠。

因此,在進行產品選型時,您需要綜合考慮各個MQ產品的特點和適用場景。如果您需要處理大數據量的消息隊列,可以考慮kafka或者商業版本的rocketmq。如果您對消息的可靠性要求較高,可以選擇rabbitmq或者商業版本的rocketmq。

如何保證消息不丟失?

首先,我們要檢查可能導致消息丟失的部分:

  • 生產者將消息發送到消息隊列伺服器;
  • 消息隊列伺服器宕機;
  • 消息隊列伺服器未將消息刷新到磁碟;
  • 消息隊列將消息發送給消費者。

image

然後根據每一步開始分析如何保證消息不丟失;

RocketMQ獨有的事務消息機制:

image

  1. 對於使用Kafka、RocketMQ、RabbitMQ的情況,它們都有消息確認機制。例如,消息只有在到達消息隊列後才會返回確認信息。RocketMQ還有獨有的事務消息機制,可以確認消息是否成功發送到消息隊列伺服器,並與相關業務進行關聯。當消息隊列伺服器監聽到生產者伺服器未返回成功時,會持續回調生產者伺服器,直到成功或超時。
  2. 如果消息隊列伺服器宕機,說明需要保證消息隊列的高可用性。因此,必須使用集群環境。對於RocketMQ來說,它的節點分為主節點和從節點。一旦主節點宕機,從節點會立即啟動,確保消息不丟失。但是主從同步是非同步進行的,因此需要使用Dledger集群的兩階段提交來確保超過半數的機器同步成功後才能返回給生產者。對於RabbitMQ集群,普通集群是分散存儲的,即所有集群的總和等於隊列的總數,沒有備份。這可能導致機器宕機後丟失部分數據,所以RabbitMQ有一個鏡像集群,會主動在節點之間進行同步,解決了數據丟失的問題。至於Kafka,本身允許丟失數據的情況,因此不需要對Kafka進行大量的消息可靠性優化以減少效率問題。但它有一個ack確認機制。
  3. 對於RocketMQ,可以採用非同步刷盤來確保效率,但如果要確保消息的可靠性,就需要使用同步刷盤機制,即損失一部分效率。對於RabbitMQ,可以設置隊列持久化來確保消息刷盤。
  4. 當消息隊列將消息投遞給消費者時,消費者自己需要採取相應的策略。對於RocketMQ、RabbitMQ和Kafka,都應將消息的偏移量設置為手動提交,而不是自動提交。否則,如果某個消費者消費失敗,該條消息將會丟失。

如何保證消息消費的冪等性?

為了保證消息消費的冪等性,我們可以採取以下策略。首先,在生產者端,我們需要為每條消息設置一個唯一的業務ID,確保消息的唯一性。這可以通過生成全局唯一的UUID或者使用分散式ID生成演算法來實現。

然後,在消費端,我們可以利用一些中間件,比如Redis,來記錄已經消費過的消息。這可以通過將消費過的消息的業務ID存儲在Redis中來實現。在消費端處理消息之前,我們首先查詢Redis,判斷當前消息的業務ID是否已經存在。如果存在,說明該消息已經被消費過,可以直接忽略。如果不存在,說明該消息是新的,可以進行消費處理。

通過以上的策略,我們可以確保消息的冪等性,避免重覆消費同一條消息。同時,使用中間件來記錄已經消費過的消息,可以提高查詢效率和降低存儲空間的占用。這樣,即使消費端出現異常或者重啟,也能夠保證消息的消費狀態不會丟失,從而保證消息消費的可靠性。

如何保證消息的順序

如何保證消息的順序呢?雖然消息隊列(MQ)本身可以保證局部的消息順序,但並不能保證全局的消息順序。這是因為在實際的系統中,為了提高可用性,通常會使用多個隊列來存儲消息,而無法將同一個業務的消息全部放入同一個隊列中。因此,需要瞭解各種MQ的特性。

image

RocketMQ提供了有序隊列的實現機制。它在主題(Topic)和隊列(Queue)之間引入了一個Message Select機制,可以將同一個業務的消息發送到同一個隊列中,從而保證消息的有序性。在消費端,如果你使用OrderMessageListen監聽器來消費消息,它會在獲取消息時,鎖定一個隊列,將該隊列中的消息全部消費完,然後再獲取下一個隊列的消息。這樣就能夠保證消息的有序消費。

相比之下,RabbitMQ和Kafka並沒有專門提供對消息順序的支持。如果你確實需要保證消息的順序,你可以將隊列和消費者設置成一個,這樣就能夠保證有序性。但是這種方式效率較低,因此在實際應用中,需要仔細考慮是否真的需要使用有序性。

總之,在設計消息消費時,需要根據實際情況來選擇是否需要保證消息的順序。如果確實需要有序性,可以考慮使用RocketMQ等支持有序隊列的MQ,或者將隊列和消費者設置成一個。但需要註意,有序性可能會犧牲一定的性能,因此需要權衡利弊來做出決策。


如何保證消息的高效讀寫

傳統文件複製方式: 需要對文件在記憶體中進行四次拷貝。

image

讀寫操作涉及到IO操作,而有關IO操作的優化,我們會想到零拷貝技術。在這方面,Kafka和RocketMQ都採用了零拷貝技術來優化文件讀寫性能。

零拷貝: 有兩種方式, mmap和transfile

image

  • RocketMQ是一個分散式消息隊列系統,它也使用了零拷貝技術來提高性能。RocketMQ通過使用DirectByteBuffer和FileChannel來實現零拷貝。
    在消息發送過程中,RocketMQ使用DirectByteBuffer作為消息緩衝區,並將消息直接寫入到DirectByteBuffer中,而無需將數據從用戶空間複製到內核緩衝區。然後,RocketMQ使用FileChannel將DirectByteBuffer中的數據直接寫入到磁碟文件中,避免了數據的多次複製。

在消息消費過程中,RocketMQ同樣使用DirectByteBuffer作為消息緩衝區,並使用FileChannel將磁碟文件中的數據直接讀取到DirectByteBuffer中,而無需將數據從內核緩衝區複製到用戶空間。

通過使用DirectByteBuffer和FileChannel,RocketMQ實現了零拷貝,從而提高了消息發送和消費的效率和性能。

  • 在讀取和寫入消息時,Kafka利用零拷貝技術來提高性能。具體來說,Kafka使用操作系統的"sendfile"系統調用,該調用允許直接將文件中的數據發送到網路套接字,而無需將數據從內核緩衝區複製到應用程式緩衝區。這樣可以避免數據的多次複製,提高了數據傳輸的效率。
    此外,Kafka還使用了mmap(記憶體映射)技術,它可以將磁碟文件映射到記憶體中。通過使用mmap,Kafka可以避免將數據從磁碟讀取到內核緩衝區,而是直接將文件映射到記憶體中,從而實現快速的數據讀取和寫入。

總的來說,Kafka通過使用"sendfile"系統調用和mmap技術來實現零拷貝,提高了數據的傳輸效率和性能。

使用MQ如何保證分散式事務的最終一致性?

分散式事務是一種要求只要有一個系統處理失敗,整個事務都失敗的機制。換句話說,要麼所有的系統都成功地完成了它們的處理,要麼所有的系統都失敗了。這樣可以確保數據的一致性。

最終一致性則是指在分散式系統中,允許存在中間狀態,只要最終的狀態保持一致即可,而不必要求強一致性。

在實現分散式事務和最終一致性時,有一些關鍵的優化策略:

  • 首先,生產者在完成業務處理後,必須確保消息被正確地投遞到MQ伺服器。這是為了防止消息丟失,因為如果消息丟失,就無法保證整個事務的一致性。
  • 其次,消費者需要保證消息的消費具有冪等性,即不會重覆消費同一條消息。這可以通過在消費端記錄已經消費過的消息的標識來實現。這樣即使有重覆的消息投遞到消費者,消費者也可以正確地處理,而不會對業務數據造成重覆影響。

讓你設計一個MQ,你會如何設計?

首先,基於現有的MQ基礎上進行定製化設計,不可放飛自我,避免漫無邊際。可以站在現有MQ的巨人肩膀上,確保設計的東西不會出現漏洞。

  • 設計隊列時,可以選擇使用阻塞隊列(blockingmq),將消息作為實體存放在隊列中,包括消息體、消息ID等內容。同時,需要考慮單隊列如何進行擴容和縮容的設計。
  • 為了提高分散式和效率,可以設計成多隊列的形式。在多隊列的情況下,引入一個中間角色來保存消息,並根據一定的策略將消息放入隊列中,比如輪詢等方式,以保證隊列的均衡。此外,需要考慮生產者的消息確認機制,確保消息的可靠性。
  • 為了確保MQ的高可用性,可以設計MQ的高可用集群,保證系統在面對故障時能夠自動切換,提供持續穩定的服務。
  • 在多消費者情況下,需要考慮如何從隊列中獲取消息,併進行消費。可以與隊列形成多對一的關係,確保消息能夠被所有消費者平均消費。
  • 為了進一步優化MQ的性能,可以考慮使用一些技術,比如順序寫、零拷貝等,提高數據傳輸的效率。
  • 最後,可以根據需求定製一些高級功能,如延遲隊列、死信隊列、有序隊列等,以滿足不同場景下的需求。

總結

MQ(Message Queue)是一種重要的技術,用於實現應用程式之間的非同步通信,提高系統的可擴展性和可靠性。在選用MQ產品時,需要考慮以下幾個方面:

  • 瞭解不同MQ產品的特點和適用場景,根據實際需求進行產品選型。
  • 為了保證消息的可靠傳遞,可以採用持久化機制,確保消息不會丟失。
  • 冪等性是保證消息消費的重要概念,可以通過唯一標識和消息狀態進行判斷。
  • 保證消息的順序可以採用單一消費者或者分區有序的方式。
  • 高效讀寫可以通過批量發送和接收消息、消息壓縮等方式進行優化。
  • 在分散式環境下,確保事務的最終一致性可以通過兩階段提交或者最大努力通知等方式實現。
  • 在設計一個自己的MQ時,需要考慮消息的存儲和傳輸方式、高可用集群的設計、多消費者消費的問題以及性能優化和定製高級功能等方面。

通過對這些面試題的瞭解和思考,可以更好地理解MQ的作用和設計原則,為面試和實際應用提供參考。


您的分享是我們最大的動力!

-Advertisement-
Play Games
更多相關文章
  • **原文鏈接:** [使用 Go 語言實現二叉搜索樹](https://mp.weixin.qq.com/s/2wYRmG_AiiHYjLDEXg94Ag) 二叉樹是一種常見並且非常重要的數據結構,在很多項目中都能看到二叉樹的身影。 它有很多變種,比如紅黑樹,常被用作 `std::map` 和 `s ...
  • ### 你可以按照以下步驟製作自己的Python模塊: 1.創建一個新的.py文件,並定義你自己的函數或類。 2.編寫文檔字元串docstring,說明該函數或類的作用、參數和返回值說明等。 3.給你的函數或類添加恰當的註釋。 4.將該.py文件放在工程目錄的一個新文件夾中,這個文件夾就是你的模塊。 ...
  • ## 概述 Mybatis 的核心組件如下所示: - Configuration:用於描述 MyBatis 的主配置信息,其他組件需要獲取配置信息時,直接通過 Configuration 對象獲取。除此之外,MyBatis 在應用啟動時,將 Mapper 配置信息、類型別名、TypeHandler ...
  • 大家好,我是棧長。 經過 Spring Cloud Alibaba 2022 的第一個候選版本 2022.0.0.0-RC1 發佈 7 個多月後,中間還有一個 2022.0.0.0-RC2 版本,就在前幾天,**Spring Cloud Alibaba 2022.0.0.0 正式版** 終於正式發佈 ...
  • 在 Protocol Buffers (protobuf) 中,可以使用特定的選項來指定生成的 JSON 標簽。通過在消息定義中使用 `[(json_name)]` 選項,可以控制生成的 JSON 欄位名稱。這樣可以確保 Protocol Buffers 和 JSON 之間的互操作性。 下麵是一個示 ...
  • ## 一、問題是怎麼發現的 最近有個新系統開發完成後要上線,由於系統調用量很大,所以先對核心介面進行了一次壓力測試,由於核心介面中基本上只有純記憶體運算,所以預估核心介面的壓測QPS能夠達到上千。 壓測容器配置:4C8G 先從10個併發開始進行發壓,結果cpu一下就飆升到了100%,但是核心介面的qp ...
  • 編程基礎常識 一、註釋 1、對代碼的說明與解釋,它不會被編譯執行,也不會顯示在編譯結果中 2、註釋分為:單行註釋和多行註釋 3、用#號開始,例如:#這是我的第一個python程式 4、註釋可以寫在單獨一行,也可以寫在一句代碼後面 5、不想執行編譯,又不能刪除的代碼,可以先用#註釋掉,代碼批量註釋用C ...
  • 要解決多線程併發問題,常見的手段無非就幾種。加鎖,如使用synchronized,ReentrantLock,加鎖可以限制資源只能被一個線程訪問;CAS機制,如AtomicInterger,AtomicBoolean等原子類,通過自旋的方式來嘗試修改資源;還有本次我們要介紹的ThreadLocal類 ...
一周排行
    -Advertisement-
    Play Games
  • 移動開發(一):使用.NET MAUI開發第一個安卓APP 對於工作多年的C#程式員來說,近來想嘗試開發一款安卓APP,考慮了很久最終選擇使用.NET MAUI這個微軟官方的框架來嘗試體驗開發安卓APP,畢竟是使用Visual Studio開發工具,使用起來也比較的順手,結合微軟官方的教程進行了安卓 ...
  • 前言 QuestPDF 是一個開源 .NET 庫,用於生成 PDF 文檔。使用了C# Fluent API方式可簡化開發、減少錯誤並提高工作效率。利用它可以輕鬆生成 PDF 報告、發票、導出文件等。 項目介紹 QuestPDF 是一個革命性的開源 .NET 庫,它徹底改變了我們生成 PDF 文檔的方 ...
  • 項目地址 項目後端地址: https://github.com/ZyPLJ/ZYTteeHole 項目前端頁面地址: ZyPLJ/TreeHoleVue (github.com) https://github.com/ZyPLJ/TreeHoleVue 目前項目測試訪問地址: http://tree ...
  • 話不多說,直接開乾 一.下載 1.官方鏈接下載: https://www.microsoft.com/zh-cn/sql-server/sql-server-downloads 2.在下載目錄中找到下麵這個小的安裝包 SQL2022-SSEI-Dev.exe,運行開始下載SQL server; 二. ...
  • 前言 隨著物聯網(IoT)技術的迅猛發展,MQTT(消息隊列遙測傳輸)協議憑藉其輕量級和高效性,已成為眾多物聯網應用的首選通信標準。 MQTTnet 作為一個高性能的 .NET 開源庫,為 .NET 平臺上的 MQTT 客戶端與伺服器開發提供了強大的支持。 本文將全面介紹 MQTTnet 的核心功能 ...
  • Serilog支持多種接收器用於日誌存儲,增強器用於添加屬性,LogContext管理動態屬性,支持多種輸出格式包括純文本、JSON及ExpressionTemplate。還提供了自定義格式化選項,適用於不同需求。 ...
  • 目錄簡介獲取 HTML 文檔解析 HTML 文檔測試參考文章 簡介 動態內容網站使用 JavaScript 腳本動態檢索和渲染數據,爬取信息時需要模擬瀏覽器行為,否則獲取到的源碼基本是空的。 本文使用的爬取步驟如下: 使用 Selenium 獲取渲染後的 HTML 文檔 使用 HtmlAgility ...
  • 1.前言 什麼是熱更新 游戲或者軟體更新時,無需重新下載客戶端進行安裝,而是在應用程式啟動的情況下,在內部進行資源或者代碼更新 Unity目前常用熱更新解決方案 HybridCLR,Xlua,ILRuntime等 Unity目前常用資源管理解決方案 AssetBundles,Addressable, ...
  • 本文章主要是在C# ASP.NET Core Web API框架實現向手機發送驗證碼簡訊功能。這裡我選擇是一個互億無線簡訊驗證碼平臺,其實像阿裡雲,騰訊雲上面也可以。 首先我們先去 互億無線 https://www.ihuyi.com/api/sms.html 去註冊一個賬號 註冊完成賬號後,它會送 ...
  • 通過以下方式可以高效,並保證數據同步的可靠性 1.API設計 使用RESTful設計,確保API端點明確,並使用適當的HTTP方法(如POST用於創建,PUT用於更新)。 設計清晰的請求和響應模型,以確保客戶端能夠理解預期格式。 2.數據驗證 在伺服器端進行嚴格的數據驗證,確保接收到的數據符合預期格 ...