冪等性、順序性保障以及消息積壓

冪等性

概念

在應用程序中,冪等性就是指對一個系統進行重復調用(相同參數),不論請求多少次,這些請求對系統的影響都是相同的效果.

比如數據庫的select操作.不同時間兩次查詢的結果可能不同,但是這個操作是符合冪等性的.冪等性指的是對資源的影響,而不是返回結果,查詢操作對數據資源本身不會產生影響,之所以結果不同,可能是因為兩次查詢之間有其他操作對資源進行了修改.

比如i++這個操作,就是非冪等性的,如果調用方沒有控制好邏輯,一次流程重復調用好幾次,結果
就會不同。

MQ的冪等性介紹
對于MQ而言,冪等性是指同一條消息,多次消費,對系統的影響是相同的
一般消息中間件的消息傳輸保障分為三個層級。
1.At most once:最多一次.消息可能會丟失,但絕不會重復傳輸.
2.Atleastonce:最少一次.消息絕不會丟失,但可能會重復傳輸。
3.Exactlyonce:恰好一次.每條消息肯定會被傳輸一次且僅傳輸一次.

RabbitMQ支持"最多一次"和"最少一次".
對于"恰好一次",目前RabbitMQ還做不到,不僅是RabbitMQ,目前市面上主流的消息中間件,都做不到這一點
在業務使用中,對于可靠性要求比較高的場景,建議使用”最少一次",以防止消息丟失,最多一次"會因為消息發送過程中,網絡問題,消費出現異常等種種原因,導致消息丟失


以下場景可能會導致消息發送重復(包含但不限于)

發送時消息重復:當一條消息已被成功發送到服務端并完成持久化,此時出現了網絡閃斷或者客戶
端宕機,導致服務端對客戶端應答失敗,如果此時Producer意識到消息發送失敗并嘗試再次發送消
息,Consumer后續會收到兩條內容相同并且MessageID也相同的消息.

投遞時消息重復:消息消費的場景下,消息已投遞到consumer并完成業務處理,當客戶端給服務端反饋應答的時候網絡閃斷,為了保證消息至少被消費一次,云消息隊列RabbitMQ版的服務端將在網絡恢復后再次嘗試投遞之前已被處理過的消息,Consumer后續會收到兩條內容相同并且Message ID也相同的消息.

解決方案

為了避免同一消息重復消費的話,我們可以通過以下方案來解決:

全局唯一 ID 設置:
每一個消息都有唯一的 ID 進行標識,我們可以使用 redis 緩存過已經消費過的消息ID,當消費的時候先查閱 redis 是否存在這個 ID ,如果不存在則進行消費,消費成功后將消息ID 存儲到 Reids 中,如果存在則不消費這條消息


業務邏輯判斷:
例如:通過檢查數據庫中是否已存在相關數據記錄,或者使用樂觀鎖機制來避免更新已被其他事務更改的數據,再或者在處理消息之前,先檢查相關業務的狀態,確保消息對應的操作尚未執行,然后才進行處理,具體根據業務場景來處理

順序性保障

消息的順序性是指消費者消費的消息和生產者發送消息的順序是一致的。

比如生產者發送的消息分別是msgl,msg2,msg3,那么消費者也是按照msgl,msg2,msg3的順序進行消費的.

很多業務場景下,消息的消費是不用保證順序的,比如使用MQ實現訂單超時的處理,但有些業務場景,可能存在多個消息順序處理的情況,比如用戶信息修改,對同一個用戶的同一個資料進行修改,需要保證消息的順序。

一些資料顯示RabbitMQ的消息能夠保障順序性,這是不嚴謹的,在不考慮消息丟失,網絡故障等異常的
情況下,如果只有一個消費者,最好也只有一個生產者的情況下,是可以保證消息的順序性,如果有多個
生產者同時發送消息,無法確定消息到達RabbitMQBroker的前后順序,也就無法驗證消息的順序性.
哪些情況可能會打破RabbitMQ的順序性呢?下面介紹幾種常見的場景:
1.多個消費者:當隊列配置了多個消費者時,消息可能會被不同的消費者并行處理,從而導致消息處理
的順序性無法保證
2.網絡波動或異常:在消息傳遞過程中,如果出現網絡波動或異常,可能會導致消息確認(ACK)丟失,從
而使得消息被重新入隊和重新消費,造成順序性問題。
3.消息重試:如果消費者在處理消息后未能及時發送確認,或者確認消息在傳輸過程中丟失,那么MQ
可能會認為消息未被成功消費而進行重試,這也可能導致消息處理的順序性問題
4.消息路由問題:在復雜的路由場景中,消息可能會根據路由鍵被發送到不同的隊列,從而無法保證全
局的順序性。
5.死信隊列:消息因為某些原因(如消費端拒絕消息)被放入死信隊列,死信隊列被消費時,無法保證消息
的順序和生產者發送消息的順序一致
包括但不僅限于以上幾種情形會使RabbitMQ消息錯序,如果要保證消息的順序性,需要業務方使用
RabbitMQ之后做進一步的處理

實現方案

消息順序性保障分為:局部順序性保證和全局順序性保證
局部順序性通常指的是在單個隊列內部保證消息的順序,全局順序性是指在多個隊列或多個消費者之間保證消息的順序。

在實際應用中,全局順序性很難實現,可以考慮使用業務邏輯來保證順序性,比如在消息中嵌入序列號,
并在消費端進行排序處理,相對而言,局部順序性更常見,也更容易實現

RabbitMQ作為一個分布式消息隊列,主要優化的是吞吐量和可用性,而不是嚴格的順序性保證,如果業
務場景確實需要嚴格的消息順序,可能需要在應用層面進行額外的設計和實現

實現策略:
1.單隊列單消費者
最簡單的方法是使用單個隊列,并由單個消費者進行處理,同一個隊列中的消息是先進先出的,這是
RabbitMQ來幫助我們保證的.

2.分區消費
單個消費者的吞吐太低了,當需要多個消費者以提高處理速度時,可以使用分區消費,把一個隊列分割成
多個分區,每個分區由一個消費者處理,以此來保持每個分區內消息的順序性
RabbitMQ本身并不支持分區消費,需要業務邏輯去實現,或者借助spring-cloud-stream來實現,官方文檔:https://docs.spring.io/spring-cloud-stream/reference/rabbit/rabbit_partitions.html

3.業務邏輯實現

消息積壓

消息積壓是指在消息隊列(如RabbitMQ)中,待處理的消息數量超過了消費者處理能力,導致消息在隊列
中不斷堆積的現象.

通常有以下幾種原因:
1.消息生產過快:在高流量或者高負載的情況下,生產者以極高的速率發送消息,超過了消費者的處理能力。

2.消費者處理能力不足:消費者處理處理消息的速度跟不上消息生產的速度,也會導致消息在隊列中積壓.
可能原因有:
1)消費端業務邏輯復雜,耗時長
2)消費端代碼性能低
3)系統資源限制,如CPU、內存、磁盤I/O等也會限制消費者處理消息的效率。
4)異常處理處理不當,消費者在處理消息時出現異常,導致消息無法被正確處理和確認

3.網絡問題:因為網絡延遲或不穩定,消費者無法及時接收或確認消息,最終導致消息積壓

4.RabbitMQ服務器配置偏低
消息積壓可能會導致系統性能下降,影響用戶體驗,甚至導致系統崩潰,因此,及時發現消息積壓并解決
對于維護系統穩定性至關重要。

解決方案

遇到消息積壓時,首先要分析消息積壓造成的原因,根據原因來調整策略。

主要從以下幾個方面來解決:

  1. 提高消費者效率
    a. 增加消費者實例數量,比如新增機器
    b. 優化業務邏輯,比如使用多線程來處理業務
    c. 設置prefetchCount,當一個消費者阻塞時,消息轉發到其他未阻塞的消費者.
    d. 消息發生異常時,設置合適的重試策略,或者轉入到死信隊列

  2. 限制生產者速率,比如流量控制,限流算法等。
    a. 流量控制:在消息生產者中實現流量控制邏輯,根據消費者處理能力動態調整發送速率
    b. 限流:使用限流工具,為消息發送速率設置一個上限
    c. 設置過期時間,如果消息過期未消費,可以配置死信隊列,以避免消息丟失,并減少對主隊列的壓力

  3. 資源與配置優化.比如升級RabbitMQ服務器的硬件,調整RabbitMQ的配置參數等

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/diannao/98408.shtml
繁體地址,請注明出處:http://hk.pswp.cn/diannao/98408.shtml
英文地址,請注明出處:http://en.pswp.cn/diannao/98408.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

算法訓練營DAY58 第十一章:圖論part08

拓撲排序精講 卡碼網:117. 軟件構建(opens new window) 題目描述: 某個大型軟件項目的構建系統擁有 N 個文件,文件編號從 0 到 N - 1,在這些文件中,某些文件依賴于其他文件的內容,這意味著如果文件 A 依…

如何在Python中使用正則表達式?

在Python中使用正則表達式主要通過內置的re模塊實現。正則表達式用于匹配、查找、替換字符串中的特定模式,是處理文本的強大工具。以下是使用正則表達式的核心方法和示例: 一、基本用法步驟 導入re模塊:import re定義正則表達式模式&#xff…

用 Trae 玩轉 Bright Data MCP 集成

引言 在自動化與智能體浪潮中,Trae 以“開箱即用、所見即所得”的工具編排體驗,成為個人與團隊落地 AI 工作流的高效選擇。本篇將以 Trae 為主角,展示如何通過最少配置完成與 Bright Data MCP 的對接,并快速構建一個可用、可觀測…

大數據Spark(六十三):RDD-Resilient Distributed Dataset

文章目錄 RDD-Resilient Distributed Dataset 一、RDD五大特性 二、RDD創建方式 RDD-Resilient Distributed Dataset 在 Apache Spark 編程中,RDD(Resilient Distributed Dataset,彈性分布式數據集)是 Spark Core 中最基本的數…

java,通過SqlSessionFactory實現動態表明的插入和查詢(適用于一個版本一個表的場景)

1,測試實體類package org.springblade.sample.test;import com.baomidou.mybatisplus.annotation.TableName; import lombok.Data;/*** Author: 肖揚* CreateTime: 2025-09-05* Description: SqlSessionFactoryTest測試* Version: 1.0*/ Data TableName("session_factory_…

鷓鴣云光儲流程系統全新升級:視頻指引與分階段模塊使用指南

鷓鴣云光儲流程系統近日完成重要更新,全面優化了操作指引體系,為用戶帶來更高效、直觀的使用體驗。本次升級重點推出了全套功能操作視頻,并明確了不同業務階段的核心模塊使用指南,助力用戶快速上手、提升工作效率。全覆蓋視頻操作…

ChatGPT 協作調優:把 SQL 查詢從 5s 優化到 300ms 的全過程

ChatGPT 協作調優:把 SQL 查詢從 5s 優化到 300ms 的全過程 🌟 Hello,我是摘星! 🌈 在彩虹般絢爛的技術棧中,我是那個永不停歇的色彩收集者。 🦋 每一個優化都是我培育的花朵,每一個…

復雜計算任務的智能輪詢優化實戰

目錄 復雜計算任務的智能輪詢優化實戰 一、輪詢方法介紹 二、三種輪詢優化策略 1、用 setTimeout 替代 setInterval 2、輪詢時間指數退避 3、標簽頁可見性檢測(Page Visibility API) 三、封裝一個簡單易用的智能輪詢方法 四、結語 作者&#xff…

Java開發中常用CollectionUtils方式,以及Spring中CollectionUtils常用方法示例

場景 Java開發中常用的CollectionUtils 一、Spring Framework的CollectionUtils 包路徑&#xff1a;org.springframework.util.CollectionUtils 核心方法&#xff1a; isEmpty(Collection<?> coll) List<String> list null; boolean empty CollectionUtil…

人工智能學習:Transformer結構(文本嵌入及其位置編碼器)

一、輸入部分介紹 輸入部分包含: 編碼器源文本嵌入層及其位置編碼器 解碼器目標文本嵌入層及其位置編碼器 在transformer的encoder和decoder的輸入層中,使用了Positional Encoding,使得最終的輸入滿足: 這里,input_embedding是通過常規embedding層,將每一個詞的…

? 肆 ? ? 默認安全建設方案:c-1.增量風險管控

&#x1f44d;點「贊」&#x1f4cc;收「藏」&#x1f440;關「注」&#x1f4ac;評「論」 在金融科技深度融合的背景下&#xff0c;信息安全已從單純的技術攻防擴展至架構、合規、流程與創新的系統工程。作為一名從業十多年的老兵&#xff0c;將系統闡述數字銀行安全體系的建設…

第二課、熟悉Cocos Creator 編輯器界面

本文主要介紹Cocos Creator 編輯器界面中幾個常規的面板功能&#xff0c;讓新手了解編輯器界面中常規的面板功能&#xff0c;更好的使用Cocos Creator 編輯器。一、編輯器界面常規面板劃分Cocos Creater編輯器默認樣式如上&#xff0c;主要包含&#xff1a;1、工具欄&#xff0…

Elixir通過Onvif協議控制IP攝像機,擴展ExOnvif的攝像頭連續移動功能 ContinuousMove

Elixir 通過Onvif 對IP設備進行控制時&#xff0c;可以使用 ExOnvif 庫。ExOnvif官方文檔 此文章僅提供了ContinuousMove的控制方式及示例。 Elixir Onvif協議控制IP設備的其他命令&#xff0c;可以參考以下鏈接 絕對移動 【AbsoluteMove】 調用指定預置位 【GotoPreset】 …

android studio JNI 環境配置實現 java 調用 c/c++

1、在 app 級的 build.gradle 文件配置兩個地方 android{ defaultConfig{ // 在 defaultConfig 里配置下面代碼 externalNativeBuild { cmake { cppFlags "-frtti -fexceptions"//添加對 c 的異常處理支持 …

靜態時序分析詳解之時序路徑類型

目錄 一、概覽 二、時序路徑 2.1 數據路徑 2.2 時鐘路徑 2.3 時鐘門控路徑 2.4 異步路徑 2.5 關鍵路徑 2.6 False路徑 2.7 單周期路徑 2.8 多周期路徑 2.9 最長路徑和最短路徑 三、參考資料 一、概覽 ? ?靜態時序分析通過模擬最差條件下分析所有的時序路徑&am…

SpringBoot埋點功能技術實現方案深度解析:架構設計、性能優化與擴展性實踐

SpringBoot埋點功能技術實現方案深度解析&#xff1a;架構設計、性能優化與擴展性實踐 1. 原理剖析與技術實現細節 1.1 埋點技術基本原理 埋點&#xff08;Tracking&#xff09;是通過在代碼中植入特定邏輯&#xff0c;收集用戶行為數據、系統運行狀態和業務指標的技術手段。在…

自建prometheus監控騰訊云k8s集群

自建prometheus監控騰訊云k8s集群 使用場景 k8s集群&#xff08;騰訊云容器服務&#xff09; promtheus (外部自建服務) 騰訊云提供了容器內部自建 Prometheus 監控 TKE 集群的文檔&#xff0c;參考。 當前的環境promethues建在k8S外的云服務器上&#xff0c;與上面鏈接文…

2025高教社國賽數學建模C題參考論文(含模型和代碼)

2025 年高教社杯大學生數學建模競賽 C 題參考論文 目錄 NIPT 的時點選擇與胎兒的異常判定 摘要 1 問題重述 2 問題分析 2.1 問題 1 分析 2.2 問題 2 分析 2.3 問題 3 分析 2.4 問題 4 分析 3 模型假設與符號定義 3.1 模型假設 4. 孕周在 10-25 周內檢測有…

iOS開發環境搭建及打包流程

一、下載xcode 直接去蘋果商店的appstore下載就行 二、clone項目 1.登錄xcode蘋果賬號或對應代碼倉庫賬號 2.clone項目 3.安裝設備真機環境&#xff08;未安裝過的話&#xff09; 三.安裝cocoapods 1. 檢查并更新 Ruby 環境 CocoaPods 是基于 Ruby 編寫的&#xff0c;因此…

數據結構之鏈表(單向鏈表與雙向鏈表)

一&#xff0c;鏈表描述鏈表是一種常見的重要的數據結構,是動態地進行存儲分配的一種結構。常用于需存儲的數據的數目無法事先確定。1.鏈表的一般結構鏈表的組成&#xff1a; 頭指針&#xff1a;存放一個地址&#xff0c;該地址指向一個元素 結點&#xff1a;用戶需要的實際數據…