消息隊列MQ(一)

来源:https://www.cnblogs.com/ft-greate/archive/2020/02/24/12355263.html
-Advertisement-
Play Games

消息隊列 為什麼要用消息隊列,都有什麼優缺點? 要問的是消息隊列都有哪些場景,然後項目里具體實現的什麼場景,你在這個場景里用的什麼消息隊列? 期望的回答是,你們公司有個什麼業務,這個業務場景有什麼技術挑戰,如果不用MQ可能會很麻煩,但是你現在用了MQ帶給你什麼好處? 場景比較多,但是比較核心的是3個 ...


消息隊列

為什麼要用消息隊列,都有什麼優缺點?

  • 要問的是消息隊列都有哪些場景,然後項目里具體實現的什麼場景,你在這個場景里用的什麼消息隊列?

  • 期望的回答是,你們公司有個什麼業務,這個業務場景有什麼技術挑戰,如果不用MQ可能會很麻煩,但是你現在用了MQ帶給你什麼好處?

  • 場景比較多,但是比較核心的是3個:解耦、非同步、削峰

解耦

​ 需要去考慮你負責的系統中是否有類似的場景,一個系統調用了多個系統和模塊,互相之間的調用很複雜,維護起來很麻煩。但是這個調用並不需要直接同步調用介面,如果用MQ給它非同步化解耦,也是可以的,你就需要 考慮在你的項目中,是不是可以運用這個MQ去進行解耦。在簡歷中體現出來

非同步化

非同步化可以大幅度提升高延遲介面的性能

削鋒:

未使用MQ的時候:

 

 

使用MQ以後:

 

系統架構中引入MQ後可能存在的缺陷:

  • 系統可用性降低:系統引入的外部依賴越多,越容易掛掉。

  • 系統的複雜性更高:需要考慮的問題越多

  • 一致性問題

 

問題2:kafka,activeMq,rabbitMq,rocketMq 都有什麼優缺點?

特性ACTIVEMQRABBITMQROCKETMQKAFKA
單擊吞吐量 萬級吞吐量,相比RocketMq和Kafka要第一個數量級 萬級,吞吐量相比RocketMq和 Kafka要低一個數量級 10萬級,RocketMq也是可以支撐高吞吐的一種MQ 10萬級別,吞吐量高,一般是配合大數據系統來進行實時的數據計算,日誌採集等場景。
時效性 ms級 微妙級,這是RabbitMq的一大特點,延時是最低的 ms級 ms級別以內
可用性 高,基於主從架構實現高可用性 高,基於主從架構實現高可用性 非常高,分散式架構 分散式,比較高,一個數據多個副本,少數機器宕機,不會丟失數據,不會導致不可用
消息可靠性 有較低的概率丟失消息   經過參數優化配置,可以做到0丟失 經過參數優化配置,可以做到0丟失
功能支持 MQ領域的功能極其完備 基於erlang開發,所以併發能力很強,性能極其好,延時很低 MQ的功能比較完備的,開始分散式的,擴展性比較好 功能較為簡單,主要支持簡單的MQ的功能,在大數據領域的實時計算和日誌採集都支持的比較好
優劣勢總結 非常成熟,業內大量的公司在使用;<br />偶爾會丟失消息,官方維護的比較少了<br />而且主要是基於解耦和非同步來用的,較少在大規模吞吐的場景中使用 基於erlang開發,所以併發能力很強,延時很低;MQ功能比較完備。而且開源版本提供的管理界面非常棒,用起來好用。 社區相對比較活躍,幾乎每個月都要發佈幾個版本,但是吞吐量只有幾萬,比較低,而且erlang開發,國內沒有幾個公司做erlang級別的源碼級別的研究和定製;很難去看懂源碼,公司對這個中間件的掌控能力比較多,只能依靠開源社區的版本迭代 API簡單易用,而且是阿裡開源項目,質量還是可以肯定的。日處理消息可以達上百億之多,可以做大規模吞吐,分散式擴展也方便,社 區維護開可以,由於是java開發的,所以可以方便的閱讀源碼,定製自己公司的mq.  
TOPIC數量對吞吐量的影響     topic可以達到幾百,幾千個級別,吞吐量有較小幅度的降低 topic可以達到幾百,幾千個級別,吞吐量有較小幅度的降低

 

如何保證消息隊列的高可用?

問的是你用的哪種MQ,是如何保證高可用的?

  1. RabbitMQ的高可用性

    RabbitMQ是比較有代表性的,因為主要是基於主從做高可用的,我們就以他為例講第一種MQ的高可用性的具體實現

    1. 單擊模式

      就是Demo級別的,一般是本地啟動體驗一下

    2. 普通集群模式

      多台機器啟動多個rabbitMq實例,每個機器啟動一個,但是你創建的queue只會放在一個rabbitmq實例上,但是每個實例同步queue的元數據,完了你消費完以後,實際上如果你連接到另外一個實例, 那麼這個實例會從queue所在實例上拉取數據過來。

      缺點:可能會在rabbitMq集群內部產生大量的數據傳輸

      ​ 可用性幾乎沒有什麼保障,如果queue所在實例的節點的機器宕機了,整個消息隊列都不可用

      圖解:

​ 3.鏡像集群模式

​ 這個才是rabbit高可用的解決方案,創建的queue,無論元數據還是queue里的消息都會存在與多個實例中,然後每次寫消息到queue中時,都會自動把消息放到多個實例的queue中進行數據同步。

 

如何開啟鏡像策略:

​ 在rabbitMq有一個管理控制台,在後臺新增一個策略,這個策略就是鏡像集群模式的策略,指定的時候可以要求數據同步到所有節點,也可以要求同步到指定數量的節點,然後再次創建queue時,應用這個策略,就會自動同步數據到其他節點上

4.kafka的高可用性:

一個最基本的架構認識,多個broker組成,每個broker是一個節點,創建一個topic,這個topic可以劃分為多個partition,每個partition可以存在與不同的broker上,每個partiton就放一部分數據。

kafka是一個天然的分散式的消息隊列,就是說一個topic的數據分佈在多個機器上面,每個機器就放一部分數據

 

 

如何保證消息不被重覆消費?如何保證消費的時候是冪等?

冪等性:

一條數據或者一個請求,給你重覆來多次,你得確保對應的數據是不會改變的,不能出錯

如何保證冪等呢?

​ 一條數據重覆出現了兩次,資料庫里只有一條數據,這就保證了系統的冪等性

(1) 比如拿到數據要入庫,你先根據主鍵查一下,如果這個數據有了,就別再插入了,update一下就好

(2) 比如是寫redis,那就沒問題,因為是set,天然冪等的。

(3) 如果不是以上所述的場景,你需要讓生產者發送數據的時候,添加一個全局唯一的ID,然後到了消費者的時候,現根據id去排查,之前是否消費過? 如果沒有就處理,然後這個ID 寫入到map或者redis中;如果消費過了,那就別處理了,保障消息不被重覆處理即可;

 

如何保證消息的可靠性傳輸?要是消息丟了怎麼辦?

1).生產者弄丟數據

​ 生產者將數據發送到rabbitmq的時候,可能數據就在半路給弄丟了,因為網路原因,都用可能

​ 此時可以選擇用rabbitmq提供的事務功能,就是生產者發送數據之前開啟rabbitMQ事務(channel.txSelect)

,然後發送消息,如果消息沒有成功被rabbitmq接收到,那麼生產者會收到異常報錯,此時就可以回滾事務(channel.txRollback),然後嘗試重發消息;如果收到消息,那麼可以提交事務(channel.txCommit).但是問題是,rabbitMQ事務機制一搞,吞吐量就會下來,因為太耗性能。

 

 

2).MQ自己弄丟了數據

對於rabbitMQ,可以開啟持久化,寫入的消息以後會持久化到磁碟里,哪怕是mq自己掛了,恢復之後會自動讀取之前存儲的數據;

設置持久化有兩個步驟:

  1. ​ 創建queue的時候將其設置為持久化,這樣就可以保證rabbitmq持久化queue的元數據,但是不會持久化queue裡面的數據;

  2. 發送消息的時候將消息 deliveryMode 設置為2,就是將消息設置為持久化,此時,rabbitMQ就會將消息持久化到磁碟里。 因此必須要同時設置這兩個持久化才行

 

總結: 生產者處的方案:開啟confirm模式,通過回調介面來得知是否成功發送到MQ

​ MQ內部的方案: 通過持久化到磁碟的方式,避免機器宕機導致記憶體中的數據丟失

​ 消費者處的方案: 關閉 autoAck ,當消費者消費並處理完後手動進行ACK

3).Kafka

  1. kafka消費者端丟失數據

    ​ 唯一可能導致消費者端丟失數據的情況,在消費到這個消息的時候,消費者那邊自動提交了ofttset,讓kafka以為你已經消費了這個消息;其實剛準備處理消息,還沒處理完 ,就已經掛了,此時這條消息就已經丟了。

    ​ 因為kafka會自動提交offset,那麼只要關閉自動提交offset,在處理玩以後再提交,就能夠避免這一類問題

  2. kafka自己丟失數據

    即kafka某個broker所在的機器宕機了,然後重新選partition的leader時,要是此時其他的follower還沒同步完數據,leader掛了,就造成數據的丟失。

一般要求有如下設置步驟:

  • 給這個topic 設置 replication.factor參數 ,這個數值必須大於1,要求每個partition至少有2個副本

  • 在kafka服務端設置 min.insync.replicas參數,這個數值必須大於1,這個要求一個leader至少感知到至少一個follower還跟自己保持聯繫,這樣才能保證leader掛了以後還有一個follower。

  • 在producer端設置 acks=null : 這個要求生產者在寫消息,必須寫入leader,而且同步到所有的follower之後,生產者才會認為這條消息已經寫入了kafka中 ;

  • 在procuduer端設置 retries=max(很大很大的值):這個要求一旦寫入失敗,就無限重試,卡在這裡

  1. 生產者會不會丟失數據

    如果按照上面的思路設置 acks=null,一定不會丟失,因為leader收到消息後,要同步數據到所有的follower後,才認為本次寫入消息成功,否則生產者會不斷重試寫入,無限重試。

 

 

 

如何保證消息的順序性?

先看看順序出錯的場景

  • rabbitMQ:一個queue,多個consumer;這就明顯亂了

  • kafka: 一個topic,一個partition,一個consumer,多個線程去併發處理,就可能產生順序錯亂

rabbitMQ如何保證消息的順序性:如果有多個消費者,就配置多個queue,將需要保證順序的消息全部寫到一個queue里,這樣就能保證消息的順序性

kafka順序性問題

 1個topic,3個partition,3個consumer,每個消費者消費一個partition,需要保證順序的消息都放入同一個partiton,但是如果一個消費者開啟多個線程來處理,還是無法保證消息的順序性。

kafka如何保證消息的順序性:

​ 解決辦法:每個消費者內部設置多個記憶體隊列,對消息的key做hash,將需要保證順序的消息映射到同一個記憶體隊列中,每個線程負責處理一個記憶體隊列

 

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

​ 本質針對的場景是,消費端出問題了,不消費了,或者消費端消費速度很慢,可能消息隊列集群的磁碟都快滿了,都沒消費者來消費,導致整個就積壓了幾個小時,這個時候該怎麼辦?

 

RabbitMQ中由於消息積壓導致過期被清理了怎麼辦

  假設你用的是rabbitmq,rabbitmq是可以設置過期時間的,就是TTL,如果消息在queue中積壓超過一定的時間就會被rabbitmq給清理掉,這個數據就沒了。

  這就不是說數據會大量積壓在mq里,而是大量的數據會直接搞丟。

  這個情況下,就不是說要增加consumer消費積壓的消息,因為實際上沒啥積壓,而是丟了大量的消息。

  我們可以採取一個方案,就是批量重導。就是大量積壓的時候,我們當時就直接丟棄數據了,然後等過了高峰期以後,這個時候我們就開始寫程式,將丟失的那批數據,寫個臨時程式,一點一點的查出來,然後重新灌入mq裡面去,把白天丟的數據給他補回來。

  假設1萬個訂單積壓在mq裡面,沒有處理,其中1000個訂單都丟了,你只能手動寫程式把那1000個訂單給查出來,手動發到mq里去再補一次

 

 

如果讓你來寫一個消息隊列,該如何進行架構設計?說一下你的思路?

  1. 首先這個MQ得支持可伸縮性,就是需要的時候快速擴容,就可以增加吞吐量和容量,如何搞? 設計一個分散式的系統唄,參考kafka的設計理念, broker->topic->partition ,每個partition放一個機器,就存一部分數據。如果現在資源不夠,就給topic增加partition(分區),然後做數據遷移,增加機器,就可以存放更多數據,提供更高的吞吐量。。。

  2. 其次要考慮這個MQ是否需要持久化到磁碟,肯定是要的,比如MQ進程掛了,數據還保存在磁碟中,導致數據不丟失。如何落地到磁碟?順序寫,這樣就沒有磁碟隨機讀取的定址開銷,磁碟順序讀寫的性能是很高的,這就是 Kafka的設計理念

  3. 其次還得考慮MQ的可用性,參照Kafka的高可用的策略。多副本->leader&follower->broker 掛了重新選舉leader即可對外服務

  4. 能不能支持0數據丟失,可以參照Kafka的數據零丟失方案

    其實MQ是一個相當複雜的東西

 


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

-Advertisement-
Play Games
更多相關文章
  • 哈嘍..大家好 很久沒有更新了,今天就來一篇最近開發用到的功能,那就是中英文切換,這個實際上也不是高大上,先說一下原理,在.NET Core框架中給我們提供了全球化的類,叫做Localization,其官方的文檔地址傳送門。 在我的項目中,我是這樣操作的,你想用別的方式,也可以看文檔自己去搞。這個已 ...
  • .NET web開發者在開發過程中,一定都踩過的坑,明明修改了js文件,可是部署到生產環境,客戶反饋說:“還是報錯啊”。。然後一臉懵逼的去伺服器上看文件,確實已經更新了。有經驗的coder可能就想到了,肯定是客戶端瀏覽器緩存搞的鬼。 此時會告訴客戶,請Crtl+F5刷新一下,這時,客戶會說:“Ctr ...
  • 前言 在兩年多以前就聽聞 Blazor 框架,是 .Net 之父的業餘實驗性項目,其目的是探索 .Net 與 WebAssembly 的相容性和應用前景。現在這個項目已經正式成為 Asp.Net Core 框架的一部分,公開了預覽版,官方教程也基本寫好上線了。就著這個機會,順便體驗一下這個框架用起來 ...
  • 本筆記摘抄自:https://www.cnblogs.com/PatrickLiu/p/8176974.html,記錄一下學習過程以備後續查用。 一、引言 今天我們要講行為型設計模式的第十個模式--備忘錄模式,先從名稱上來看。備忘錄模式可以理解為對某個對象的狀態進行保存,等到需要恢復的時 候,可以從 ...
  • 如今,當談到 WPF 時,我們言必稱 MVVM、框架(如 Prism)等,似乎已經忘了不用這些的話該怎麼使用 WPF 了。當然,這裡說的不用框架和 MVVM,並不是說像使用 Winform 那樣使用 WPF,而是追本溯源,重識 WPF 與生俱來的綁定和命令的風采。 ...
  • 微信公眾號:【 "Dotnet9的博客" 】,網站:【 "Dotnet9" 】,問題或建議:【 "請網站留言" 】, 如果對您有所幫助:【 "歡迎贊賞" 】。 開源C WPF控制項庫系列: "(一)開源C WPF控制項庫《MaterialDesignInXAML》" "(二)開源C WPF控制項庫《Pan ...
  • 本筆記摘抄自:https://www.cnblogs.com/PatrickLiu/p/8135083.html,記錄一下學習過程以備後續查用。 一、引言 今天我們要講行為型設計模式的第九個模式--訪問者模式。如果按老規矩,先從名稱上來看這個模式,我根本不能獲得任何對理解該模式有用的信息, 而且這個 ...
  • Linux命令學習 命令分類: 文件處理命令 許可權管理命令 文件搜索命令 幫助命令 用戶管理命令 壓縮解壓命令 網路命令 關機重啟命令 1、文件處理命令 命令格式:命令 [-選項] [參數] 例:ls -la /etc 說明:1)個別命令使用不遵循此格式 2)當有多個選項時,可以寫在一起 3)簡化選 ...
一周排行
    -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.數據驗證 在伺服器端進行嚴格的數據驗證,確保接收到的數據符合預期格 ...