這些MQ概念你都懂嗎:死信隊列、重試隊列、消息回溯等

2020-12-11 51CTO

本文轉載自微信公眾號「搬運工來架構」,作者cocodroid 。轉載本文請聯繫搬運工來架構公眾號。

消息隊列(MQ)的基本概念,很多時候都要了解清楚,這樣在學消息隊列中間件就比較能夠遊刃有餘,遇到不清楚的也可以重新翻來看看,加深理解。這裡有關於:優先級隊列、延遲隊列、死信隊列、重試隊列、消息回溯、消息堆積、消息追蹤/消息軌跡、消息過濾、消息審計、消息路由等的介紹。

01.優先級隊列

優先級隊列不同於先進先出隊列,優先級高的消息具備優先被消費的特權,這樣可以為下遊提供不同消息級別的保證。不過這個優先級也是需要有一個前提的:如果消費者的消費速度大於生產者的速度,並且消息中間件伺服器(一般簡單的稱之為Broker)中沒有消息堆積,那麼對於發送的消息設置優先級也就沒有什麼實質性的意義了,因為生產者剛發送完一條消息就被消費者消費了,那麼就相當於Broker中至多只有一條消息,對於單條消息來說優先級是沒有什麼意義的。

02.延遲隊列

當你在網上購物的時候是否會遇到這樣的提示:「三十分鐘之內未付款,訂單自動取消」?這個是延遲隊列的一種典型應用場景。延遲隊列存儲的是對應的延遲消息,所謂「延遲消息」是指當消息被發送以後,並不想讓消費者立刻拿到消息,而是等待特定時間後,消費者才能拿到這個消息進行消費。延遲隊列一般分為兩種:基於消息的延遲和基於隊列的延遲。基於消息的延遲是指為每條消息設置不同的延遲時間,那麼每當隊列中有新消息進入的時候就會重新根據延遲時間排序,當然這也會對性能造成極大的影響。實際應用中大多採用基於隊列的延遲,設置不同延遲級別的隊列,比如5s、10s、30s、1min、5mins、10mins等,每個隊列中消息的延遲時間都是相同的,這樣免去了延遲排序所要承受的性能之苦,通過一定的掃描策略(比如定時)即可投遞超時的消息。

03.死信隊列

由於某些原因消息無法被正確的投遞,為了確保消息不會被無故的丟棄,一般將其置於一個特殊角色的隊列,這個隊列一般稱之為死信隊列。與此對應的還有一個「回退隊列」的概念,試想如果消費者在消費時發生了異常,那麼就不會對這一次消費進行確認(Ack),進而發生回滾消息的操作之後消息始終會放在隊列的頂部,然後不斷被處理和回滾,導致隊列陷入死循環。為了解決這個問題,可以為每個隊列設置一個回退隊列,它和死信隊列都是為異常的處理提供的一種機制保障。實際情況下,回退隊列的角色可以由死信隊列和重試隊列來扮演。

04.重試隊列

重試隊列其實可以看成是一種回退隊列,具體指消費端消費消息失敗時,為防止消息無故丟失而重新將消息回滾到Broker中。與回退隊列不同的是重試隊列一般分成多個重試等級,每個重試等級一般也會設置重新投遞延時,重試次數越多投遞延時就越大。舉個例子:消息第一次消費失敗入重試隊列Q1,Q1的重新投遞延遲為5s,在5s過後重新投遞該消息;如果消息再次消費失敗則入重試隊列Q2,Q2的重新投遞延遲為10s,在10s過後再次投遞該消息。以此類推,重試越多次重新投遞的時間就越久,為此需要設置一個上限,超過投遞次數就入死信隊列。重試隊列與延遲隊列有相同的地方,都是需要設置延遲級別,它們彼此的區別是:延遲隊列動作由內部觸發,重試隊列動作由外部消費端觸發;延遲隊列作用一次,而重試隊列的作用範圍會向後傳遞。

05.消費模式之推模式push

對於kafka而言,由Broker主動推送消息至消費端,實時性較好,不過需要一定的流制機制來確保服務端推送過來的消息不會壓垮消費端。

06.消費模式之拉模式pull

對於kafka而言,消費端主動向Broker端請求拉取(一般是定時或者定量)消息,實時性較推模式差,但是可以根據自身的處理能力而控制拉取的消息量。

07.消息回溯

一般消息在消費完成之後就被處理了,之後再也不能消費到該條消息。消息回溯正好相反,是指消息在消費完成之後,還能消費到之前被消費掉的消息。對於消息而言,經常面臨的問題是「消息丟失」,至於是真正由於消息中間件的缺陷丟失還是由於使用方的誤用而丟失一般很難追查,如果消息中間件本身具備消息回溯功能的話,可以通過回溯消費復現「丟失的」消息進而查出問題的源頭之所在。消息回溯的作用遠不止與此,比如還有索引恢復、本地緩存重建,有些業務補償方案也可以採用回溯的方式來實現。

08.消息堆積

流量削峰是消息中間件的一個非常重要的功能,而這個功能其實得益於其消息堆積能力。從某種意義上來講,如果一個消息中間件不具備消息堆積的能力,那麼就不能把它看做是一個合格的消息中間件。消息堆積分內存式堆積和磁碟式堆積。

09.消息追蹤/軌跡

對於分布式架構系統中的鏈路追蹤(trace)而言,大家一定不會陌生。對於消息中間件而言,消息的鏈路追蹤(以下簡稱消息追蹤)同樣重要。對於消息追蹤最通俗的理解就是要知道消息從哪來,存在哪裡以及發往哪裡去。基於此功能下,我們可以對發送或者消費完的消息進行鏈路追蹤服務,進而可以進行問題的快速定位與排查。想要知道消息發送成功了嗎?發送的消息在消費端為什麼消費不到?為什麼又會重複消費?等等問題。引入消息軌跡可以知道消息從生產者觸發,經由broker等代理存儲,再到消費者消費的整個過程,各個節點的狀態、時間、地點等數據匯聚而成完整的鏈路信息。

10.消息過濾

消息過濾是指按照既定的過濾規則為下遊用戶提供指定類別的消息。就以kafka而言,完全可以將不同類別的消息發送至不同的topic中,由此可以實現某種意義的消息過濾,或者Kafka還可以根據分區對同一個topic中的消息進行分類。不過更加嚴格意義上的消息過濾應該是對既定的消息採取一定的方式按照一定的過濾規則進行過濾。同樣以Kafka為例,可以通過客戶端提供的ConsumerInterceptor接口或者Kafka Stream的filter功能進行消息過濾。對於rocketmq來說,支持Tag、SQL92和類過濾器(新版去除)等3種模式。

11.消息審計

消息審計是指在消息在生產、存儲和消費的整個過程之間對消息個數及延遲的審計,以此來檢測是否有數據丟失、是否有數據重複、端到端的延遲又是多少等。有關產品:Uber的Chaperone、LinkedIn的kafka monitor、Confluent Control Center等,有需要或感興趣可自行通過網絡了解下。

12.消息路由

將消息路由到指定的隊列中,消費者消費隊列裡的消息。RabbitMQ可以從交換器Exchanger根據路由鍵路由到指定一個或多個隊列。kafka默認是按照消息主題進行路由,消息路由在kafka中使用場景較少,使用起來也比較麻煩,如無特殊需要,一般不推薦使用。

參考資料

《深入理解Kafka》

http://www.likecs.com/default/index/show?id=14248

【編輯推薦】

【責任編輯:

武曉燕

TEL:(010)68476606】

點讚 0

相關焦點

  • RabbitMQ 消費端限流、TTL、死信隊列
    整合RabbitMq ,一篇講完,然後還帶大家用Hyperf+RabbitMQ+WebSocket實現大屏幕消息推送(藍字點擊可跳轉),今天這篇,為大家講講RabbitMQ的消費端限流、TTL、死信隊列相關內容。
  • 消息隊列:Rabbitmq如何保證不丟消息
    >生產者將信道設置成confirm模式,一旦信道進入confirm模式,所有在該信道上面發布的消息都會被指派一個唯一的ID(從1開始),一旦消息被投遞到所有匹配的隊列之後,broker就會發送一個確認給生產者(包含消息的唯一ID),這就使得生產者知道消息已經正確到達目的隊列了,如果消息和隊列是可持久化的,那麼確認消息會將消息寫入磁碟之後發出,broker回傳給生產者的確認消息中deliver-tag
  • 《RabbitMQ》如何保證消息的可靠性
    ,我們可以進行消息補償,也就是消息的重試機制。spring: rabbitmq: # 支持消息發送失敗後重返隊列 publisher-returns: true # 開啟消息確認機制 publisher-confirm-type: correlated listener: simple: retry: # 開啟重試
  • 詳解SpringCloud中RabbitMQ消息隊列原理及配置,一篇就夠!
    key都是固定的。是springboot要求的。是通過自定義的模糊匹配規則來決定消息存儲在哪些隊列中。當Producer發送消息到RabbitMQ中時,MQ中的交換器會根據路由鍵來決定消息應該發送到哪些隊列中。Java知音公眾號內回復「後端面試」,送你一份Java面試題寶典Consumer同樣是註冊一個監聽器到隊列,監聽隊列狀態,當隊列狀態發生變化時,消費消息。
  • 想了解 Kafka, RabbitMQ, ZeroMQ, RocketMQ, ActiveMQ 之間的差異?這一篇文章就夠了!
    、消息回溯十六、消息重試十七、並發度Kafka:中。1>消息被投遞到哪個隊列是由交換器和key決定的,交換器、路由鍵、隊列都需要手動創建。rabbitmq客戶端發送消息要和broker建立連接,需要事先知道broker上有哪些交換器,有哪些隊列。通常要聲明要發送的目標隊列,如果沒有目標隊列,會在broker上創建一個隊列,如果有,就什麼都不處理,接著往這個隊列發送消息。
  • rabbitmq隊列之發送消息到指定隊列
    這裡是你的朝花夕拾、樂於分享動漫、生活小竅門、java程序小工具等給大家今天來分享一個:寫入消息到rabbitmq的java開發小工具類。(筆者已經製作成集MQ發送和接收並生成日誌文件的腳本小工具,需要的可以私聊我,我看到的話會第一時間回復給你。)
  • 想了解Kafka,RabbitMQ,ZeroMQ,RocketMQ,ActiveMQ之間的差異?這一篇文章就夠了!
    、消息回溯十六、消息重試十七、並發度Kafka:中。1>消息被投遞到哪個隊列是由交換器和key決定的,交換器、路由鍵、隊列都需要手動創建。rabbitmq客戶端發送消息要和broker建立連接,需要事先知道broker上有哪些交換器,有哪些隊列。通常要聲明要發送的目標隊列,如果沒有目標隊列,會在broker上創建一個隊列,如果有,就什麼都不處理,接著往這個隊列發送消息。
  • 淺入淺出消息隊列
    相信在學生時代大家都遇到過上面的這種情況,如果我們將在學校上課抽象成一個系統,那這種情況就是一個很常見的消息隊列的使用場景。在上述實例中,要提的問題就是**「消息」,提問題的學生是「生產者」,回答問題的老師是「消費者」,收集問題的課代表是「消息隊列」**。
  • RabbitMQ 3.0.3 發布,高級消息隊列服務
    基於Erlang的高級消息隊列RabbitMQ 3.0.3 發布。2013-03-06 之前版本是2013-01-31的3.0.2 主要是bug 修復。
  • RabbitMQ的5種核心消息模式都不懂,也敢說會用消息隊列
    摘要以前看過的關於RabbitMQ核心消息模式的文章都是基於JavaAPI的,最近看了下官方文檔,發現這些核心消息模式都可以通過Spring AMQP來實現。於是總結了下RabbitMQ的實用技巧,包括RabbitMQ在Windows和Linux下的安裝、5種核心消息模式的Spring AMQP實現,相信對於想要學習和回顧RabbitMQ的朋友都會有所幫助。
  • 五分鐘學後端技術:如何學習後端工程師必學的消息隊列
    什麼是消息隊列「RabbitMQ?」「Kafka?」「RocketMQ?」...在日常學習與開發過程中,我們常常聽到消息隊列這個關鍵詞,可能你是熟練使用消息隊列的老手,又或者你是不懂消息隊列的新手,不論你了不了解消息隊列,本文都將帶你搞懂消息隊列的一些基本理論。
  • 如何使用Spring Boot與RabbitMQ結合實現延遲隊列
    延遲重試。比如消費者從隊列裡消費消息時失敗了,但是想要延遲一段時間後自動重試。如果不使用延遲隊列,那麼我們只能通過一個輪詢掃描程序去完成。這種方案既不優雅,也不方便做成統一的服務便於開發人員使用。但是使用延遲隊列的話,我們就可以輕而易舉地完成。如何實現?
  • IM開發基礎知識補課(五):通俗易懂,正確理解並用好MQ消息隊列
    因此,對於即時通訊開發者來說,正確地理解MQ消息隊列,對於IM或消息推送系統的架構設計、方案選型等都大有裨益。3.5 應用場景5:即時消息通訊即時消息通訊是指,消息隊列一般都內置了高效的通信機制,因此也可以用在純的即時消息通訊場景。比如實現點對點消息隊列或者IM聊天室等(但Jack Jiang認為,在中大型IM系統中,MQ並不適合這麼用,具體的討論請見:《請教可以使用MQ消息隊列中間件做即時通訊系統嗎?》)。
  • Linux-C 編程 / 進程通信 / 實現基於SysV消息隊列的文件伺服器
    一、簡介3 種 System V IPC:System V 消息隊列的特點:面向消息,即每次讀寫的對象都是消息,區別於管道、FIFO 以及 UNIX domain 流 socket;具有內核持久性缺點:通過標識符引用,而不是文件描述符,不符合 unix 一切皆文件的設計;使用鍵而不是文件名來標識消息隊列,程序編寫比較複雜;無連接,內核不會像對待管道、FIFO 以及 socket 那樣維護引用隊列的進程數,需要程式設計師謹慎考慮何時刪除一個消息隊列才是安全的;相關API
  • 基於有限狀態機與消息隊列的第三方支付系統補單實踐
    我們採用了通過消息隊列進行即時補償的方式,如圖4所示。補償消費者並沒有去做補償工作,而是解析消息然後通過RPC調用支付核心暴露的補償接口。為什麼不在消費者中直接補償?這麼做主要是考慮將邏輯收斂到一處便於維護。
  • RabbitMQ是如何確定消息是否投遞到隊列中的
    前言在使用RabbitMQ消息中間件時,因為消息的投遞是異步的,默認情況下,RabbitMQ會刪除那些無法路由的消息。為了能夠檢出消息是否順利投遞到隊列,我們需要相應的處理機制。今天就來驗證一下相關的驗證機制。2. 消息投遞失敗那麼哪些情況消息會投遞失敗呢?
  • RabbitMQ 高頻考點
    Nack (not acknowledged) 消息給你,你可以進行重試操作。4.6  死信隊列 跟 延遲隊列4.6.1 死信隊列死信 Dead Letter 是 RabbitMQ 中的一種消息機制,當消費消息時隊列裡的消息出現以下情況那麼該消息將成為死信。
  • 熬夜整理的RabbitMQ知識點相當齊全的文章
    交換器,用來接收生產者發送的消息並將這些消息路由給伺服器中的隊列,簡而言之:即將消息路由給隊列;(4)Binding:綁定,用於將消息隊列綁定、關聯到指定的交換器;即用於消息隊列和交換器之間的關聯;那如何將其關聯、綁定在一起呢,通過路由鍵RoutingKey實現;即通過 路由鍵RoutingKey將 交換器Exchange 和 消息隊列 Queue 連接起來的,從另外一個角度上看,也可以將交換器Exchange
  • 輕量級消息隊列RedisQueue
    消息隊列(Message Queue)是分布式系統必不可少的中間件,大部分消息隊列產品(如RocketMQ/RabbitMQ/Kafka等)要求團隊有比較強的技術實力,不適用於中小團隊,並且對.NET技術的支持力度不夠。而Redis實現的輕量級消息隊列很簡單,僅有Redis常規操作,幾乎不需要開發團隊掌握額外的知識!
  • 騰訊T4總結消息隊列+協議+RabbitMQ+ActiveMQ+Kafka+RocketMQ真香
    消息中間件適用於需要可靠的數據傳送的分布式環境。採用消息中間件機制的系統中,不同的對象之間通過傳遞消息來激活對方的事件,完成相應的操作。發送者將消息發送給消息伺服器,消息伺服器將消息存放在若干隊列中,在合適的時候再將消息轉發給接收者。