偷偷摘套内射激情视频,久久精品99国产国产精,中文字幕无线乱码人妻,中文在线中文a,性爽19p

RocketMQ消息丟失如何排查?

開(kāi)發(fā) 前端
我們?cè)赗ocketMQ-Dashboard上其實(shí)就能看到每個(gè)隊(duì)列broker端的offset(代理者位點(diǎn))以及消息消費(fèi)的offset(消費(fèi)者位點(diǎn)),差值就是沒(méi)有被消費(fèi)的消息。

消息丟失如何排查?當(dāng)我們?cè)谑褂胢q的時(shí)候,經(jīng)常會(huì)遇到消息消費(fèi)異常的問(wèn)題,原因有很多種,比如:

  • producer發(fā)送失敗
  • consumer消費(fèi)異常
  • consumer根本就沒(méi)收到消息

「那么我們?cè)撊绾闻挪榱?」

其實(shí)借助RocketMQ-Dashboard就能高效的排查,里面有很多你想象不到的功能。

首先我們先查找期望消費(fèi)的消息,查找的方式有很多種,根據(jù)消息id,時(shí)間等。

「消息沒(méi)找到?」

說(shuō)明proder發(fā)送異常,也有可能是消息過(guò)期了,因?yàn)閞ocketmq的消息默認(rèn)保存72h,此時(shí)到producer端的日志進(jìn)一步確認(rèn)即可。

「消息找到了!」

接著看消息的消費(fèi)狀態(tài),如下圖消息的消費(fèi)狀態(tài)為NOT_ONLINE。

「NOT_ONLINE代表什么含義呢?」

別著急,我們一步步來(lái)分析,先看看TrackType到底有多少種狀態(tài)。

public enum TrackType {
CONSUMED,
CONSUMED_BUT_FILTERED,
PULL,
NOT_CONSUME_YET,
NOT_ONLINE,
UNKNOWN
}

每種類(lèi)型的解釋如下:

類(lèi)型

解釋

CONSUMED

消息已經(jīng)被消費(fèi)

CONSUMED_BUT_FILTERED

消息已經(jīng)投遞但被過(guò)濾

PULL

消息消費(fèi)的方式是拉模式

NOT_CONSUME_YET

目前沒(méi)有被消費(fèi)

NOT_ONLINE

CONSUMER不在線

UNKNOWN

未知錯(cuò)誤

「怎么判定消息已經(jīng)被消費(fèi)?」

上一節(jié)我們講到,broker會(huì)用一個(gè)map來(lái)保存每個(gè)queue的消費(fèi)進(jìn)度,「如果queue的offset大于被查詢消息的offset則消息被消費(fèi),否則沒(méi)有被消費(fèi)」(NOT_CONSUME_YET)。

我們?cè)赗ocketMQ-Dashboard上其實(shí)就能看到每個(gè)隊(duì)列broker端的offset(代理者位點(diǎn))以及消息消費(fèi)的offset(消費(fèi)者位點(diǎn)),差值就是沒(méi)有被消費(fèi)的消息。

當(dāng)消息都被消費(fèi)時(shí),差值為0,如下圖所示:

「CONSUMED_BUT_FILTERED表示消息已經(jīng)投遞,但是已經(jīng)被過(guò)濾掉了」。例如producer發(fā)的是topicA,tagA,但是consumer訂閱的卻是topicA,tagB。

「CONSUMED_BUT_FILTERED(消息已經(jīng)被投遞但被過(guò)濾)是怎么發(fā)生的呢?」

這個(gè)就不得不提到RocketMQ中的一個(gè)概念,「消息消費(fèi)要滿足訂閱關(guān)系一致性,即一個(gè)consumerGroup中的所有消費(fèi)者訂閱的topic和tag必須保持一致,不然就會(huì)造成消息丟失」。

如下圖場(chǎng)景,發(fā)送了4條消息,consumer1訂閱了topica-taga,而consumer2訂閱了topica-tab。consumer1消費(fèi)q0中的數(shù)據(jù),consumer2消費(fèi)q1中的數(shù)據(jù)。

投遞到q0的msg-1和msg-3只有msg-1能被正常消費(fèi),而msg-3則是CONSUMED_BUT_FILTERED。因?yàn)閙sg-3被投遞到q0,但是consumer1不消費(fèi)tagb的消息導(dǎo)致消息被過(guò)濾,造成消息丟失。

同理msg-2這條消息也會(huì)丟失。

「注意,還有一個(gè)非常重要的點(diǎn)」!

雖然消息消費(fèi)失敗了,但是消息的offset還會(huì)正常提交,即 「消息消費(fèi)失敗了,但是狀態(tài)也會(huì)是CONSUMED」。

「RocketMQ認(rèn)為消息消費(fèi)失敗需要重試的場(chǎng)景有哪些?」

  • 返回ConsumeConcurrentlyStatus.RECONSUME_LATER
  • 返回null
  • 主動(dòng)或被動(dòng)拋出異常

「那么消費(fèi)失敗的消息去哪了呢?」

當(dāng)消息消費(fèi)失敗,會(huì)被放到重試隊(duì)列中,Topic名字為%RETRY% + consumerGroup。

「Consumer沒(méi)訂閱這個(gè)topic啊,怎么才能消費(fèi)到重試消息?」

其實(shí)在Consumer啟動(dòng)的時(shí)候,框架內(nèi)部幫你訂閱了這個(gè)topic,所以重試消息能被消費(fèi)到。

「另外消息不是一直重試,而是每隔1段時(shí)間進(jìn)行重試」

第幾次重試

與上次重試的間隔時(shí)間

第幾次重試

與上次重試的間隔時(shí)間

1

10 秒

9

7 分鐘

2

30 秒

10

8 分鐘

3

1 分鐘

11

9 分鐘

4

2 分鐘

12

10 分鐘

5

3 分鐘

13

20 分鐘

6

4 分鐘

14

30 分鐘

7

5 分鐘

15

1 小時(shí)

8

6 分鐘

16

2 小時(shí)

當(dāng)消息超過(guò)最大消費(fèi)次數(shù)16次,會(huì)將消息投遞到死信隊(duì)列中,死信隊(duì)列的topic名為%DLQ% + consumerGroup。

「因此當(dāng)你發(fā)現(xiàn)消息狀態(tài)為CONSUMED,但是消費(fèi)失敗時(shí),去重試隊(duì)列和死信隊(duì)列中找就行了」。

消息消費(fèi)異常排查實(shí)戰(zhàn)

這個(gè)問(wèn)題發(fā)生的背景是這樣的,就是我們有2個(gè)系統(tǒng),中間通過(guò)mq來(lái)保證數(shù)據(jù)的一致性,結(jié)果有一天數(shù)據(jù)不一致了,那肯定是consumer消費(fèi)消息有問(wèn)題,或者producer發(fā)送消息有問(wèn)題。

先根據(jù)時(shí)間段找到了消息,確保了發(fā)送沒(méi)有問(wèn)題,接著看消息的狀態(tài)為NOT_CONSUME_YET,說(shuō)明consumer在線但是沒(méi)有消息。

「NOT_CONSUME_YET表明消息沒(méi)有被消費(fèi)」,但是消息發(fā)送都過(guò)了好長(zhǎng)時(shí)間了,consumer不應(yīng)該沒(méi)消費(fèi)啊,查日志consumer確實(shí)沒(méi)有消費(fèi)。

用RocketMQ-Dashboard查看一下代理者位點(diǎn)和消費(fèi)者位點(diǎn),0隊(duì)列正常消費(fèi),其他隊(duì)列沒(méi)有被消費(fèi)。

「感覺(jué)這個(gè)負(fù)載均衡策略有點(diǎn)問(wèn)題啊,怎么0隊(duì)列這么多消息,別的隊(duì)列都怎么沒(méi)消息,問(wèn)一波中間件的同學(xué),是不是又改負(fù)載均衡策略了?」

確實(shí)改了!測(cè)試環(huán)境下,采用隊(duì)列緯度區(qū)分多環(huán)境,0是基準(zhǔn)環(huán)境,我們團(tuán)隊(duì)目前還沒(méi)有用多環(huán)境,所以收發(fā)消息都會(huì)在隊(duì)列0上,其他隊(duì)列不會(huì)用到(「你可以簡(jiǎn)單認(rèn)為測(cè)試環(huán)境發(fā)送和消費(fèi)消息只會(huì)用到0隊(duì)列」)。

「那么問(wèn)題來(lái)了!」

首先消息的狀態(tài)是NOT_CONSUME_YET,說(shuō)明消息肯定被投遞到0隊(duì)列之外了,但是中間件的小伙伴卻說(shuō)消息不會(huì)被投遞到0隊(duì)列。

要想驗(yàn)證我的想法首先需要證明沒(méi)有被消費(fèi)的消息確實(shí)被投遞到0隊(duì)列之外的隊(duì)列了。

中間走的彎路就不說(shuō)了,直到我看了看RocketMQ-Dashboard的源碼,「發(fā)現(xiàn)Dashboard其實(shí)返回了消息的很多信息,但是并沒(méi)有在頁(yè)面展示出來(lái),直接看接口返回」。

乖乖,發(fā)現(xiàn)了新世界,消息的所有屬性都在這了,看到queuId為14,果然驗(yàn)證了我的想法。

再看bornHost居然是我們辦公室的網(wǎng)段。

「難道本地啟動(dòng)的負(fù)載均衡策略和測(cè)試環(huán)境的負(fù)載均衡策略不一樣?」

本地debug一波代碼,果然是本地的producer會(huì)往所有的隊(duì)列發(fā)送消息,并且consumer也會(huì)消費(fèi)所有隊(duì)列的消息。

「至此找出問(wèn)題了!」

producer在本地啟了一個(gè)服務(wù),注冊(cè)到測(cè)試環(huán)境的zk,測(cè)試環(huán)境的部分請(qǐng)求打到本地,往0隊(duì)列之外的隊(duì)列發(fā)了消息,但是測(cè)試環(huán)境的consumer只會(huì)消費(fèi)0隊(duì)列中的消息,導(dǎo)致消息遲遲沒(méi)有被消費(fèi)。

責(zé)任編輯:武曉燕 來(lái)源: Java識(shí)堂
相關(guān)推薦

2024-08-06 09:55:25

2023-12-21 08:01:41

RocketMQ消息堆積

2023-09-13 08:14:57

RocketMQ次數(shù)機(jī)制

2023-04-25 18:54:13

數(shù)據(jù)數(shù)據(jù)丟失

2021-08-04 07:47:18

Kafka消息框架

2025-10-16 08:34:01

2024-10-29 08:34:27

RocketMQ消息類(lèi)型事務(wù)消息

2024-11-11 13:28:11

RocketMQ消息類(lèi)型FIFO

2024-02-04 09:02:29

RocketMQ項(xiàng)目處理器

2023-12-15 13:08:00

RocketMQ中間件消費(fèi)順序

2021-02-02 11:01:31

RocketMQ消息分布式

2021-03-08 10:19:59

MQ消息磁盤(pán)

2022-12-22 10:03:18

消息集成

2021-04-27 07:52:18

RocketMQ消息投遞

2023-07-17 08:34:03

RocketMQ消息初體驗(yàn)

2022-06-02 08:21:07

RocketMQ消息中間件

2023-07-18 09:03:01

RocketMQ場(chǎng)景消息

2025-04-09 08:20:00

RocketMQ消息隊(duì)列開(kāi)發(fā)

2021-10-22 08:37:13

消息不丟失rocketmq消息隊(duì)列

2021-09-13 07:23:53

KafkaGo語(yǔ)言
點(diǎn)贊
收藏

51CTO技術(shù)棧公眾號(hào)