1. 冪等性保障
1.1 冪等性介紹
????????冪等性是數學和計算機科學中某些運算的性質,它們可以被多次應?,?不會改變初始應?的結果.
應?程序的冪等性介紹
????????在應?程序中,冪等性就是指對?個系統進?重復調?(相同參數),不論請求多少次,這些請求對系統的影響都是相同的效果.
?????????如數據庫的 select 操作.不同時間兩次查詢的結果可能不同,但是這個操作是符合冪等性的.冪等性指的是對資源的影響,?不是返回結果.查詢操作對數據資源本?不會產?影響,之所以結果不同,可能是因為兩次查詢之間有其他操作對資源進?了修改.
?????????如 i++ 這個操作,就是?冪等性的.如果調??沒有控制好邏輯,?次流程重復調?好?次,結果 就會不同.
MQ 的冪等性介紹
????????對于 MQ ??,冪等性是指同?條消息,多次消費,對系統的影響是相同的.?般消息中間件的消息傳輸保障分為三個層級.
1. At most once:最多?次.消息可能會丟失,但絕不會重復傳輸.
2. At least once:最少?次.消息絕不會丟失,但可能會重復傳輸.
3. Exactly once:恰好?次.每條消息肯定會被傳輸?次且僅傳輸?次.
????????RabbitMQ ?持"最多?次"和"最少?次".對于"恰好?次",?前 RabbitMQ 還做不到,不僅是RabbitMQ,?前市?上主流的消息中間件,都做不到 這?點.
????????在業務使?中,對于可靠性要求?較?的場景,建議使?"最少?次",以防?消息丟失.?"最多?次"會因為消息發送過程中,?絡問題,消費出現異常等種種原因,導致消息丟失.
以下場景可能會導致消息發送重復(包含但不限于)
????????? 發送時消息重復:當?條消息已被成功發送到服務端并完成持久化,此時出現了?絡閃斷或者客戶端宕機,導致服務端對客戶端應答失敗.如果此時 Producer 意識到消息發送失敗并嘗試再次發送消息, Consumer 后續會收到兩條內容相同并且 Message ID 也相同的消息.
????????? 投遞時消息重復:消息消費的場景下,消息已投遞到 Consumer 并完成業務處理,當客戶端給服務端反饋應答的時候?絡閃斷.為了保證消息?少被消費?次,云消息隊列 RabbitMQ 版的服務端將在?絡恢復后再次嘗試投遞之前已被處理過的消息,Consumer 后續會收到兩條內容相同并且 Message ID也相同的消息.
????????但是"最少?次",就會造成?個問題,消費端會收到重復的消息,也會造成對同?條消息進?多次處理.? 些不重要的
????????業務還好?點,對于重要的業務,如果不對重復的消息進?處理,會造成嚴重事故.
?????????如:當?戶對?個訂單付款之后,因為?絡問題,付款成功的結果未返回給訂單系統,當?戶再次點擊付款時,果系統未做冪等性處理,那就會造成兩次扣款。
1.2 解決方案
????????MQ 消費者的冪等性的解決?法,?般有以下?種:
全局唯? ID
????????1. 為每條消息分配?個唯?標識符,?如 UUID 或者 MQ 消息中的唯?ID,但是?定要保證唯?性.?
????????2. 消費者收到消息后,先?該 id 判斷該消息是否已經消費過,如果已經消費過,則放棄處理.
?????????3. 如果未消費過,消費者開始消費消息,業務處理成功后,把唯? ID 保存起來(數據庫或Redis等)
2. 順序性保障
2.1 順序性保障介紹
????????消息的順序性是指消費者消費的消息和?產者發送消息的順序是?致的.
?????????如?產者發送的消息分別是 msg1,msg2,msg3,那么消費者也是按照msg1,msg2,msg3的順序進?消費的.
????????很多業務場景下,消息的消費是不?保證順序的,?如使? MQ 實現訂單超時的處理.但有些業務場景,?能存在多個消息順序處理的情況.?如?戶信息修改,對同?個?戶的同?個資料進?修改,需要保證消息的順序??????
?????????些資料顯? RabbitMQ 的消息能夠保障順序性,這是不嚴謹的.在不考慮消息丟失,?絡故障等異常的情況下,如果只有?個消費者,最好也只有?個?產者的情況下,是可以保證消息的順序性.如果有多個?產者同時發送消息,?法確定消息到達 RabbitMQ Broker 的前后順序,也就?法驗證消息的順序性.哪些情況可能會打破 RabbitMQ 的順序性呢?下?介紹?種常?的場景:
??????????1. 多個消費者:當隊列配置了多個消費者時,消息可能會被不同的消費者并?處理,從?導致消息處理的順序性?法保證.
????????2. ?絡波動或異常:在消息傳遞過程中,如果出現?絡波動或異常,可能會導致消息確認(ACK)丟失,從?使得消息被重新?隊和重新消費,造成順序性問題.
????????3. 消息重試:如果消費者在處理消息后未能及時發送確認,或者確認消息在傳輸過程中丟失,那么MQ 可能會認為消息未被成功消費?進?重試,這也可能導致消息處理的順序性問題.
????????4. 消息路由問題:在復雜的路由場景中,消息可能會根據路由鍵被發送到不同的隊列,從??法保證全局的順序性.
????????5. 死信隊列:消息因為某些原因(如消費端拒絕消息)被放?死信隊列,死信隊列被消費時,?法保證消息的順序和?產者發送消息的順序?致
????????包括但不僅限于以上?種情形會使 RabbitMQ 消息錯序,如果要保證消息的順序性,需要業務?使? RabbitMQ 之后做進?步的處理
2.2 順序性保障方案
????????消息順序性保障分為:局部順序性保證和全局順序性保證.
????????局部順序性通常指的是在單個隊列內部保證消息的順序.全局順序性是指在多個隊列或多個消費者之間保證消息的順序.
????????在實際應?中,全局順序性很難實現,可以考慮使?業務邏輯來保證順序性,?如在消息中嵌?序列號,并在消費端進?排序處理.相對??,局部順序性更常?,也更容易實現.
????????RabbitMQ 作為?個分布式消息隊列,主要優化的是吞吐量和可?性,?不是嚴格的順序性保證.如果業務場景確實需要嚴格的消息順序,可能需要在應?層?進?額外的設計和實現.
接下來說?下消息的順序性保證的常?策略.
1. 單隊列單消費者
????????最簡單的?法是使?單個隊列,并由單個消費者進?處理.同?個隊列中的消息是先進先出的,這是 RabbitMQ來幫助我們保證的.
2. 分區消費
????????單個消費者的吞吐太低了,當需要多個消費者以提?處理速度時,可以使?分區消費.把?個隊列分割成多個分區,每個分區由?個消費者處理,以此來保持每個分區內消息的順序性.
?????????如?戶修改資料后,發送?條?戶資料消息.消費者在處理時,需要保證消息發送的先后順序,但這種場合并不需要保證全局順序.只需要保證同?個?戶的消息順序消費就可以.這時候就可以采 ?把消費按照?定的規則,分為多個區,每個分區由?個消費者處理?RabbitMQ 本?并不?持分區消費,需要業務邏輯去實現,或者借助 spring-cloud-stream 來實現
參考:https://docs.spring.io/spring-cloud-stream/reference/rabbit/rabbit_partitions.html
3. 消息確認機制
????????使??動消息確認機制,消費者在處理完?條消息后,顯式地發送確認,這樣 RabbitMQ 才會移除并繼續發送下?條消息.
4. 業務邏輯控制
????????在某些情況下,即使消息亂序到達,也可以在業務邏輯層?實現順序控制.?如通過在消息中嵌?序列號,并在消費時根據這些信息來處理?RabbitMQ 本?并不保證全局的嚴格順序性,特別是在分布式系統中.在實際應?開發中,根據具體的業 務需求,可能需要結合多種策略來實現所需要的順序保證.
3. 消息積壓問題
3.1 原因分析
????????消息積壓是指在消息隊列(如 RabbitMQ )中,待處理的消息數量超過了消費者處理能?,導致消息在隊列中不斷堆積的現象.
通常有以下?種原因:
? ? ? ? 1. 消息?產過快:在?流量或者?負載的情況下,?產者以極?的速率發送消息,超過了消費者的處理能?.
????????2. 消費者處理能?不?:消費者處理消息的速度跟不上消息?產的速度,也會導致消息在隊列中積壓.
????????可能原因有:
????????????????1)消費端業務邏輯復雜,耗時?
????????????????2)消費端代碼性能低
????????????????3)系統資源限制,如CPU、內存、磁盤I/O等也會限制消費者處理消息的效率.
????????????????4)異常處理不當.消費者在處理消息時出現異常,導致消息?法被正確處理和確認.
3. ?絡問題:因為?絡延遲或不穩定,消費者?法及時接收或確認消息,最終導致消息積壓
4. RabbitMQ 服務器配置偏低
????????消息積壓可能會導致系統性能下降,影響?戶體驗,甚?導致系統崩潰.因此,及時發現消息積壓并解決對于維護系統穩定性?關重要.
3.2 解決方案
????????遇到消息積壓時,?先要分析消息積壓造成的原因.根據原因來調整策略.主要從以下?個??來解決:
1. 提高消費者效率
????????a. 增加消費者實例數量,?如新增機器
????????b. 優化業務邏輯,?如使?多線程來處理業務
????????c. 設置 prefetchCount,當?個消費者阻塞時,消息轉發到其他未阻塞的消費者.
????????d. 消息發?異常時,設置合適的重試策略,或者轉?到死信隊列
2. 限制生產者速率.比如流量控制,限流算法等.
????????a. 流量控制:在消息?產者中實現流量控制邏輯,根據消費者處理能?動態調整發送速率
????????b. 限流:使?限流?具,為消息發送速率設置?個上限
????????c. 設置過期時間.如果消息過期未消費,可以配置死信隊列,以避免消息丟失,并減少對主隊列的壓?