最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

RabbitMQ消息發(fā)送失敗的重試機(jī)制核心流程

 更新時(shí)間:2025年12月26日 09:06:22   作者:Wang's Blog  
本文介紹了基于NestJS和RabbitMQ的高可靠消息重試機(jī)制設(shè)計(jì),通過三級(jí)保障機(jī)制(預(yù)持久化、實(shí)時(shí)回調(diào)處理、定時(shí)任務(wù)補(bǔ)償)和靈活的存儲(chǔ)層(支持MySQL/Redis),確保消息在發(fā)送失敗時(shí)能夠可靠重試,感興趣的朋友跟隨小編一起看看吧

核心問題

  • 確保消息在RabbitMQ投遞過程中的可靠性,通過持久化存儲(chǔ)、回調(diào)處理和定時(shí)重試解決網(wǎng)絡(luò)異常、服務(wù)宕機(jī)等場景下的消息丟失風(fēng)險(xiǎn)
  • 解決分布式系統(tǒng)中消息發(fā)送失敗時(shí)的可靠重試,確保消息不丟失和最終一致性

重試機(jī)制核心流程

1 )消息發(fā)送前持久化

  • 原因:防止消息在發(fā)送過程中因服務(wù)崩潰或網(wǎng)絡(luò)異常丟失。
  • 實(shí)現(xiàn):調(diào)用發(fā)送接口時(shí),先將消息存入數(shù)據(jù)庫,生成唯一ID(如UUID)記錄交換器、路由鍵、消息體及發(fā)送次數(shù)(初始為0)。

2 )消息發(fā)送后處理

  • 成功發(fā)送:
    • RabbitMQ確認(rèn)接收(ACK)后,立即刪除數(shù)據(jù)庫中的持久化消息,避免數(shù)據(jù)膨脹。
  • 投遞失敗:
    • 交換機(jī)不存在:觸發(fā)ConfirmCallback,標(biāo)記發(fā)送失敗,等待重試。
    • 隊(duì)列不存在:觸發(fā)ReturnCallback,重新持久化消息到數(shù)據(jù)庫(原消息已刪除)。

3 )定時(shí)任務(wù)補(bǔ)償

  • 巡檢未成功消息:定時(shí)查詢數(shù)據(jù)庫中狀態(tài)為“待發(fā)送”且未超重試次數(shù)的消息。
  • 重試策略:
    • 重試次數(shù)+1,重新投遞消息。
    • 若超過最大重試次數(shù)(如5次),標(biāo)記消息為“死亡” 并觸發(fā)告警(郵件/短信)。
  • 并發(fā)控制:多副本部署時(shí)需用分布式鎖(如Redis鎖)避免重復(fù)消費(fèi)。

關(guān)鍵業(yè)務(wù)流程與 RabbitMQ 交互

  • Confirm 回調(diào)
    • 作用:確認(rèn) RabbitMQ 是否接收消息。
    • 邏輯:
      • 若收到 ACK → 刪除數(shù)據(jù)庫記錄。
      • 若未收到 ACK → 保留記錄等待重試。
  • Return 回調(diào)
    • 場景:消息被 RabbitMQ 接收但無法路由到隊(duì)列(如路由鍵錯(cuò)誤)。
    • 處理:將消息重新持久化至數(shù)據(jù)庫,狀態(tài)保持 READY。

NestJS 服務(wù)層實(shí)現(xiàn)

1 ) 消息存儲(chǔ)接口設(shè)計(jì)(TransMessageService

// trans-message.interface.ts
export interface TransMessageService {
  saveForSend(
    exchange: string,
    routingKey: string,
    payload: string
  ): Promise<TransMessagePO>;
  deleteOnAck(id: string): Promise<void>;
  saveOnReturn(
    id: string,
    exchange: string,
    routingKey: string,
    payload: string 
  ): Promise<TransMessagePO>;
  listPendingMessages(): Promise<TransMessagePO[]>;
  incrementRetryCount(id: string): Promise<void>;
  markAsDead(id: string): Promise<void>;
}

2 ) 數(shù)據(jù)庫實(shí)現(xiàn)(TypeORM + PostgreSQL)

// trans-message.service.ts 
import { Injectable } from '@nestjs/common';
import { InjectRepository } from '@nestjs/typeorm';
import { Repository } from 'typeorm';
import { TransMessagePO } from './trans-message.entity';
@Injectable()
export class DBTransMessageService implements TransMessageService {
  constructor(
    @InjectRepository(TransMessagePO)
    private readonly repo: Repository<TransMessagePO>,
    private readonly serviceName: string 
  ) {}
  async saveForSend(exchange: string, routingKey: string, payload: string) {
    const message = new TransMessagePO();
    message.id = uuidv4();
    message.serviceName = this.serviceName;
    message.exchange = exchange;
    message.routingKey = routingKey;
    message.payload = payload;
    message.retryCount = 0;
    message.status = 'PENDING';
    return this.repo.save(message);
  }
  async deleteOnAck(id: string) {
    await this.repo.delete({ id, serviceName: this.serviceName });
  }
  // 其他方法實(shí)現(xiàn)類似,略 
}

消息發(fā)送器(TransMessageSender)

1 ) 發(fā)送消息核心邏輯

// trans-message.sender.ts
import { Injectable, Logger } from '@nestjs/common';
import { RabbitMQService } from '@golevelup/nestjs-rabbitmq';
import { TransMessageService } from './trans-message.interface';
@Injectable()
export class TransMessageSender {
  private readonly logger = new Logger(TransMessageSender.name);
  constructor(
    private readonly rmqService: RabbitMQService,
    private readonly messageService: TransMessageService
  ) {}
  async send(exchange: string, routingKey: string, payload: any) {
    const payloadString = JSON.stringify(payload);
    try {
      // 1. 持久化到數(shù)據(jù)庫
      const messagePO = await this.messageService.saveForSend(
        exchange,
        routingKey,
        payloadString
      );
      // 2. 發(fā)送到RabbitMQ
      await this.rmqService.publish(exchange, routingKey, payload, {
        messageId: messagePO.id, // 關(guān)鍵:設(shè)置消息ID
        persistent: true
      });
      this.logger.log(`Message sent: ${messagePO.id}`);
    } catch (e) {
      this.logger.error(`Send failed: ${e.message}`, e.stack);
    }
  }
}

2 ) 回調(diào)處理(Confirm & Return)

// rabbitmq.config.ts
import { RabbitMQModule } from '@golevelup/nestjs-rabbitmq';
@Module({
  imports: [
    RabbitMQModule.forRoot(RabbitMQModule, {
      exchanges: [{ name: 'orders', type: 'topic' }],
      uri: 'amqp://localhost',
      connectionInitOptions: { wait: false },
      // 注冊回調(diào)函數(shù)
      setupController: (channel) => {
        channel.on('return', (msg) => this.handleReturn(msg));
        channel.on('ack', (msg) => this.handleAck(msg));
      }
    })
  ]
})
export class AppModule {
  handleReturn(msg: ConsumeMessage) {
    const { exchange, routingKey } = msg.fields;
    const payload = msg.content.toString();
    const messageId = msg.properties.messageId; // 關(guān)鍵:獲取消息ID
    this.messageService.saveOnReturn(messageId, exchange, routingKey, payload);
  }
  handleAck(msg: ConsumeMessage) {
    const messageId = msg.properties.messageId;
    this.messageService.deleteOnAck(messageId);
  }
}

定時(shí)任務(wù)與重試控制

// retry.task.ts
import { Injectable, Logger } from '@nestjs/common';
import { SchedulerRegistry } from '@nestjs/schedule';
@Injectable()
export class RetryTask {
  private readonly logger = new Logger(RetryTask.name);
  private readonly MAX_RETRY = 5;
  constructor(
    private messageService: TransMessageService,
    private scheduler: SchedulerRegistry
  ) {
    this.startRetryCycle();
  }
  startRetryCycle() {
    const interval = setInterval(async () => {
      const messages = await this.messageService.listPendingMessages();
      for (const msg of messages) {
        if (msg.retryCount >= this.MAX_RETRY) {
          await this.messageService.markAsDead(msg.id);
          this.triggerAlert(`Message dead: ${msg.id}`);
          continue;
        }
        await this.messageService.incrementRetryCount(msg.id);
        await this.resendMessage(msg);
      }
    }, 60_000); // 每分鐘執(zhí)行 
    this.scheduler.addInterval('retry-job', interval);
  }
  private async resendMessage(msg: TransMessagePO) {
    // 調(diào)用發(fā)送器重新發(fā)送(略)
  }
}

NestJS 核心代碼實(shí)現(xiàn)

  1. 消息持久化服務(wù)層(TransMessageService
// trans-message.service.ts
import { Injectable } from '@nestjs/common';
import { TransMessage } from './entity/trans-message.entity';
import { Repository } from 'typeorm';
import { InjectRepository } from '@nestjs/typeorm';
import { MessageType } from './enums/message-type.enum';
@Injectable()
export class TransMessageService {
  constructor(
    @InjectRepository(TransMessage)
    private readonly messageRepo: Repository<TransMessage>,
    private readonly serviceName: string, // 注入服務(wù)標(biāo)識(shí)
  ) {}
  // 發(fā)送前持久化
  async createReadyMessage(
    exchange: string,
    routingKey: string,
    payload: string,
  ): Promise<TransMessage> {
    const message = this.messageRepo.create({
      id: uuidv4(),
      service: this.serviceName,
      exchange,
      routingKey,
      payload,
      sendDate: new Date(),
      sequence: 0,
      type: MessageType.READY,
    });
    return this.messageRepo.save(message);
  }
  // 發(fā)送成功刪除記錄 
  async markMessageSuccess(id: string): Promise<void> {
    await this.messageRepo.delete({ id, service: this.serviceName });
  }
  // 消息路由失敗后重新持久化
  async recreateReturnedMessage(
    exchange: string,
    routingKey: string,
    payload: string,
  ): Promise<TransMessage> {
    return this.createReadyMessage(exchange, routingKey, payload);
  }
  // 查詢待重試消息
  async listReadyMessages(): Promise<TransMessage[]> {
    return this.messageRepo.find({
      where: { type: MessageType.READY, service: this.serviceName },
    });
  }
  // 遞增重試次數(shù)
  async incrementRetryCount(id: string): Promise<void> {
    const message = await this.messageRepo.findOneBy({ id });
    if (message) {
      message.sequence += 1;
      await this.messageRepo.save(message);
    }
  }
  // 標(biāo)記消息為死亡狀態(tài)
  async markMessageDead(id: string): Promise<void> {
    const message = await this.messageRepo.findOneBy({ id });
    if (message) {
      message.type = MessageType.DEAD;
      await this.messageRepo.save(message);
    }
  }
}
  1. 消息發(fā)送器(TransMessageSender
// trans-message.sender.ts
import { Injectable, Logger } from '@nestjs/common';
import { RabbitMQService } from '@golevelup/nestjs-rabbitmq';
import { TransMessageService } from './trans-message.service';
@Injectable()
export class TransMessageSender {
  private readonly logger = new Logger(TransMessageSender.name);
  constructor(
    private readonly rmqService: RabbitMQService,
    private readonly transMessageService: TransMessageService,
  ) {}
  async send(exchange: string, routingKey: string, payload: object): Promise<void> {
    try {
      // 1. 序列化消息
      const payloadString = JSON.stringify(payload);
      // 2. 持久化到數(shù)據(jù)庫
      const message = await this.transMessageService.createReadyMessage(
        exchange,
        routingKey,
        payloadString,
      );
      // 3. 發(fā)送至 RabbitMQ
      await this.rmqService.publish(exchange, routingKey, payload, {
        messageId: message.id,
        contentType: 'application/json',
      });
      this.logger.log(`Message sent: ${message.id}`);
    } catch (e) {
      this.logger.error(`Send failed: ${e.message}`, e.stack);
    }
  }
}
  1. RabbitMQ 回調(diào)處理
// rmq.config.ts
import { RabbitMQModule } from '@golevelup/nestjs-rabbitmq';
import { TransMessageService } from './trans-message.service';
@Module({
  imports: [
    RabbitMQModule.forRoot(RabbitMQModule, {
      exchanges: [{ name: 'orders', type: 'topic' }],
      uri: 'amqp://localhost:5672',
      connectionInitOptions: { wait: false },
      // 注冊回調(diào)處理器 
      setupController: (channel) => {
        // 確認(rèn)回調(diào) 
        channel.on('ack', (msg) => {
          const messageId = msg.properties.messageId;
          this.transMessageService.markMessageSuccess(messageId);
        });
        // 返回回調(diào)
        channel.on('return', (msg) => {
          const { exchange, routingKey } = msg.fields;
          const payload = msg.content.toString();
          this.transMessageService.recreateReturnedMessage(
            exchange,
            routingKey,
            payload,
          );
        });
      },
    }),
  ],
})
export class RmqConfigModule {}
  • 消息預(yù)持久化機(jī)制
    • 發(fā)送前必須將消息持久化到數(shù)據(jù)庫,防止發(fā)送過程中因網(wǎng)絡(luò)中斷或服務(wù)崩潰導(dǎo)致消息丟失。業(yè)務(wù)系統(tǒng)調(diào)用發(fā)送接口時(shí):
    • 發(fā)送成功后的清理邏輯
  • 當(dāng) RabbitMQ 確認(rèn)(ACK)接收消息后,立即刪除數(shù)據(jù)庫中的持久化記錄,避免無效數(shù)據(jù)堆積引發(fā)存儲(chǔ)壓力。
    • 定時(shí)任務(wù)重試策略
    • 獨(dú)立進(jìn)程定時(shí)掃描狀態(tài)為 PENDING 的消息:
    • 檢查重試次數(shù)是否超限(如 ≤5次)
  • 每次重試增加 retryCount
  • 超限則標(biāo)記為 DEAD 并觸發(fā)告警

工程示例:1

1 ) 方案1:基礎(chǔ)持久化+重試(推薦)

  • 適用場景:中小型系統(tǒng)
  • 技術(shù)棧:
    • @golevelup/nestjs-rabbitmq + TypeORM + PostgreSQL
    • 消息表字段:id, serviceName, exchange, routingKey, payload, retryCount, status
  • 優(yōu)勢:實(shí)現(xiàn)簡單,依賴少

2 ) 方案2:Redis 高性能存儲(chǔ)

// redis-trans-message.service.ts
import { RedisService } from '@liaoliaots/nestjs-redis';
@Injectable()
export class RedisTransMessageService implements TransMessageService {
  private readonly KEY_PREFIX = 'msg:';
  constructor(private redisService: RedisService) {}
  async saveForSend(exchange: string, routingKey: string, payload: string) {
    const id = uuidv4();
    const client = this.redisService.getClient();
    await client.hset(`${this.KEY_PREFIX}${id}`, {
      exchange,
      routingKey,
      payload,
      retryCount: '0',
      status: 'PENDING'
    });
    return { id } as TransMessagePO;
  }
  // 其他方法通過Redis HSET/HGET/DEL實(shí)現(xiàn) 
}

3 ) 方案3:分布式事務(wù)框架集成

  • 技術(shù)棧:NestJS + RabbitMQ + Transactional Outbox 模式
  • 核心邏輯:
    • 業(yè)務(wù)操作與消息持久化在同一個(gè)數(shù)據(jù)庫事務(wù)中提交
    • 獨(dú)立進(jìn)程輪詢Outbox表并投遞消息
  • 優(yōu)勢:強(qiáng)一致性,避免業(yè)務(wù)成功但消息未存儲(chǔ)

工程示例:2

1 ) 方案 1:基礎(chǔ)數(shù)據(jù)庫重試

// task.service.ts 
@Injectable()
export class RetryTaskService {
  constructor(private readonly transMessageService: TransMessageService) {}
  @Cron('*/5 * * * * *') // 每5秒執(zhí)行
  async handleRetry() {
    const messages = await this.transMessageService.listReadyMessages();
    messages.forEach(async (msg) => {
      if (msg.sequence < 5) {
        await this.transMessageService.incrementRetryCount(msg.id);
        // 重新發(fā)送邏輯(略)
      } else {
        await this.transMessageService.markMessageDead(msg.id);
        // 觸發(fā)告警(略)
      }
    });
  }
}

2 ) 方案 2:Redis 高性能暫存

優(yōu)勢:

  • 讀寫速度比 MySQL 快 10 倍以上
  • 支持分布式鎖解決多副本并發(fā)問題
// 使用 Redis 存儲(chǔ)消息
import { Redis } from 'ioredis';
@Injectable()
export class RedisTransMessageService implements TransMessageService {
  private readonly redis = new Redis();
  async createReadyMessage(
    exchange: string,
    routingKey: string,
    payload: string,
  ): Promise<TransMessage> {
    const id = uuidv4();
    await this.redis.hset(
      `msg:${id}`,
      'payload', payload,
      'exchange', exchange,
      'routingKey', routingKey,
      'sequence', '0',
    );
    return { id, exchange, routingKey, payload, sequence: 0 };
  }
}

3 ) 方案 3:死信隊(duì)列(DLX)自動(dòng)重試

RabbitMQ 配置命令:

創(chuàng)建死信交換機(jī)和隊(duì)列
rabbitmqadmin declare exchange name=dlx type=direct
rabbitmqadmin declare queue name=dead_messages
rabbitmqadmin declare binding source=dlx destination=dead_messages routing_key=dead
主隊(duì)列綁定死信路由
rabbitmqadmin declare queue name=orders \
  arguments='{"x-dead-letter-exchange":"dlx", "x-dead-letter-routing-key":"dead"}'

NestJS 消費(fèi)死信消息:

@RabbitSubscribe({
  exchange: 'dlx',
  routingKey: 'dead',
  queue: 'dead_messages',
})
async handleDeadMessage(msg: any) {
  // 解析原始消息ID并重新持久化
  const originalMsgId = msg.properties.headers['x-original-message-id'];
  await this.transMessageService.recreateReturnedMessage(
    msg.fields.exchange,
    msg.fields.routingKey,
    msg.content.toString(),
  );
}

工程示例:3

1 ) 方案1:數(shù)據(jù)庫存儲(chǔ)方案(TypeORM)

// trans-message.service.ts
@Injectable()
export class TransMessageService {
  constructor(
    @InjectRepository(TransMessage)
    private readonly messageRepo: Repository<TransMessage>
  ) {}
  async prePersist(exchange: string, routingKey: string, payload: string) {
    const message = this.messageRepo.create({
      exchange,
      routingKey,
      payload,
      status: 'PENDING'
    });
    return this.messageRepo.save(message);
  }
  async markAsSuccess(id: string) {
    await this.messageRepo.delete(id);
  }
}

2 ) 方案2:Redis 高性能存儲(chǔ)方案

// redis-trans.service.ts
import { RedisService } from '@liaoliaots/nestjs-redis';
@Injectable()
export class RedisTransService {
  constructor(private readonly redisService: RedisService) {}
  async prePersist(exchange: string, routingKey: string, payload: string) {
    const client = this.redisService.getClient();
    const id = uuidv4();
    await client.hset(
      `msg:${id}`,
      'exchange', exchange,
      'routingKey', routingKey,
      'payload', payload,
      'status', 'PENDING'
    );
    return id;
  }
}

3 ) 方案3:混合存儲(chǔ)方案(數(shù)據(jù)庫+Redis)

  • 熱數(shù)據(jù):高頻重試消息存 Redis
  • 冷數(shù)據(jù):超限消息轉(zhuǎn)存數(shù)據(jù)庫供審計(jì)
  • 一致性保障:通過 Redis 事務(wù)確保狀態(tài)同步

關(guān)鍵配置與命令

RabbitMQ 必要設(shè)置

啟用持久化交換機(jī)和隊(duì)列
rabbitmqctl set_policy HA ".*" '{"ha-mode":"all"}' --apply-to all
監(jiān)控命令
rabbitmqctl list_queues name messages_ready messages_unacknowledged

NestJS 模塊配置

// app.module.ts
@Module({
  imports: [
    TypeOrmModule.forFeature([TransMessagePO]),
    RabbitMQModule.forRootAsync(RabbitMQModule, {
      useFactory: () => ({
        uri: process.env.RABBITMQ_URI,
        exchanges: [{ name: 'orders', type: 'topic', durable: true }]
      })
    })
  ],
  providers: [
    { provide: TransMessageService, useClass: DBTransMessageService },
    TransMessageSender,
    RetryTask
  ]
})
export class AppModule {}

RabbitMQ 周邊配置處理

1 ) NestJS 連接配置

// rabbitmq.module.ts
import { RabbitMQModule } from '@golevelup/nestjs-rabbitmq';
@Module({
  imports: [
    RabbitMQModule.forRoot(RabbitMQModule, {
      exchanges: [{ name: 'orders', type: 'topic' }],
      uri: 'amqp://user:pass@localhost:5672',
      connectionInitOptions: { wait: false }
    })
  ]
})
export class RabbitModule {}

2 ) 關(guān)鍵 Shell 命令

創(chuàng)建帶持久化的交換機(jī)
rabbitmqadmin declare exchange name=orders type=topic durable=true
監(jiān)控未路由消息
rabbitmqctl list_queues name messages_unroutable

3 ) 告警機(jī)制實(shí)現(xiàn)

// alert.service.ts
@Injectable()
export class AlertService {
  async triggerAlert(messageId: string) {
    // 集成郵件/Slack/Webhook
    await slackService.send(`消息 ${messageId} 重試超限!`);
  }
}

核心優(yōu)化點(diǎn)

  1. 消息軌跡追蹤
    通過 properties.messageId 實(shí)現(xiàn)全鏈路消息關(guān)聯(lián)
  2. 并發(fā)控制
    使用 Redis 分布式鎖防止多副本重試沖突:
    import Redlock from 'redlock';
    const lock = await redlock.acquire([`lock:${messageId}`], 5000);
    
  3. 退避策略
    指數(shù)級(jí)延長重試間隔:delay = Math.min(2 retryCount * 1000, 60000)

關(guān)鍵設(shè)計(jì)原則:

  • 所有消息操作必須冪等
  • 持久化存儲(chǔ)與 MQ 狀態(tài)需原子性同步
  • 死信消息必須提供人工干預(yù)接口

補(bǔ)充知識(shí)點(diǎn)

  1. RabbitMQ 持久化機(jī)制
    • 消息需設(shè)置 deliveryMode: 2
    • 隊(duì)列聲明時(shí)添加 durable: true
  2. NestJS 微服務(wù)模式
    // main.ts 啟用混合模式
    app.connectMicroservice<RabbitMQTransportOptions>({
      transport: Transport.RMQ,
      options: { urls: ['amqp://...'], queue: 'retry_queue' }
    });
    
  3. 監(jiān)控指標(biāo)
    • 重試成功率
    • 平均重試耗時(shí)
    • 死信隊(duì)列堆積量

關(guān)鍵問題解決方案

并發(fā)重試控制

const lockKey = `lock:msg:${msg.id}`;
const lock = await redis.set(lockKey, '1', 'EX', 30, 'NX');
if (lock) { /* 執(zhí)行重試 */ }

使用 Redis 分布式鎖確保多副本服務(wù)不會(huì)重復(fù)處理同一條消息:

消息冪等性設(shè)計(jì)

@RabbitSubscribe({ exchange: 'orders', routingKey: 'order.create' })
async handleOrderEvent(msg: any, @Message() amqpMsg) {
  const messageId = amqpMsg.properties.messageId;
  if (await this.redis.exists(`processed:${messageId}`)) return;
  // 處理業(yè)務(wù)...
}
  • 在消費(fèi)者端通過 messageId 去重,避免重復(fù)消費(fèi):
  • 性能優(yōu)化
    • 批量處理:定時(shí)任務(wù)每次拉取 100 條消息減少 DB 查詢次數(shù)。
    • 異步刪除:成功確認(rèn)后使用 setImmediate 異步刪除記錄避免阻塞主線程。

注意事項(xiàng)

  1. 消息完整性:
    • 必須設(shè)置messageIdpersistent: true確保RabbitMQ端持久化。
  2. 重試設(shè)計(jì):
    • 采用指數(shù)退避策略(如1s/5s/30s)避免雪崩。
  3. 死信處理:
    • 建議將死信轉(zhuǎn)入獨(dú)立隊(duì)列人工干預(yù)。
  4. 性能優(yōu)化:
    • 批量查詢待重試消息(如每次100條),減少DB壓力

關(guān)鍵點(diǎn):通過數(shù)據(jù)庫/REDIS雙寫、ACK回調(diào)聯(lián)動(dòng)、定時(shí)補(bǔ)償三位一體,實(shí)現(xiàn)消息的可靠投遞,適用于訂單支付、庫存同步等高可靠性場景

總結(jié)

本文實(shí)現(xiàn)了基于 NestJS + RabbitMQ 的高可靠消息重試架構(gòu),核心創(chuàng)新點(diǎn):

  1. 三級(jí)保障機(jī)制:預(yù)持久化 → 實(shí)時(shí)回調(diào)處理 → 定時(shí)任務(wù)補(bǔ)償。
  2. 靈活存儲(chǔ)層:支持 MySQL/Redis 無縫切換,適應(yīng)不同規(guī)模業(yè)務(wù)。
  3. 生產(chǎn)級(jí)方案:提供數(shù)據(jù)庫重試、Redis 高性能方案、死信隊(duì)列三種工程實(shí)現(xiàn)。

關(guān)鍵提示:

  • 重試閾值建議設(shè)為 3-5次,避免無限重試拖垮系統(tǒng)。
  • 使用 x-delay 插件實(shí)現(xiàn)指數(shù)退避重試(如 1s/3s/10s)。
  • 監(jiān)控 DEAD 狀態(tài)消息并及時(shí)介入處理。

到此這篇關(guān)于RabbitMQ: 消息發(fā)送失敗的重試機(jī)制設(shè)計(jì)與實(shí)現(xiàn)的文章就介紹到這了,更多相關(guān)RabbitMQ 消息重試機(jī)制內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

  • Idea提交代碼到gitee上實(shí)現(xiàn)方式

    Idea提交代碼到gitee上實(shí)現(xiàn)方式

    本文詳細(xì)介紹了使用Gitee和Git進(jìn)行項(xiàng)目創(chuàng)建、提交、拉取和回滾的具體步驟,包括本地與遠(yuǎn)程倉庫的操作方法,以及常用Git命令的總結(jié)和注意事項(xiàng)
    2025-10-10
  • Spring?RestTemplate如何利用攔截器打印請求參數(shù)和返回狀態(tài)

    Spring?RestTemplate如何利用攔截器打印請求參數(shù)和返回狀態(tài)

    這篇文章主要介紹了Spring?RestTemplate如何利用攔截器打印請求參數(shù)和返回狀態(tài)問題,具有很好的參考價(jià)值,希望對大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教
    2023-07-07
  • idea啟動(dòng)項(xiàng)目報(bào)端口號(hào)沖突或被占用的解決方法

    idea啟動(dòng)項(xiàng)目報(bào)端口號(hào)沖突或被占用的解決方法

    這篇文章主要介紹了idea啟動(dòng)項(xiàng)目報(bào)端口號(hào)沖突或被占用的解決方法,小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,也給大家做個(gè)參考。一起跟隨小編過來看看吧
    2018-10-10
  • JAVA 中解密RSA算法JS加密實(shí)例詳解

    JAVA 中解密RSA算法JS加密實(shí)例詳解

    這篇文章主要介紹了JAVA 中解密RSA算法JS加密 的相關(guān)資料,需要的朋友可以參考下
    2017-04-04
  • Java環(huán)境配置圖文教程(推薦)

    Java環(huán)境配置圖文教程(推薦)

    下面小編就為大家?guī)硪黄狫ava環(huán)境配置圖文教程(推薦)。小編覺得挺不錯(cuò)的,現(xiàn)在就分享給大家,也給大家做個(gè)參考。一起跟隨小編過來看看吧
    2017-09-09
  • 解讀easyexcel中的常用注解

    解讀easyexcel中的常用注解

    這篇文章主要介紹了關(guān)于easyexcel中的常用注解,具有很好的參考價(jià)值,希望對大家有所幫助,如有錯(cuò)誤或未考慮完全的地方,望不吝賜教
    2024-04-04
  • 簡單了解Java斷言利器AssertJ原理及用法

    簡單了解Java斷言利器AssertJ原理及用法

    這篇文章主要介紹了簡單了解Java斷言利器AssertJ原理及用法,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友可以參考下
    2020-11-11
  • SpringBoot中的三種應(yīng)用事件處理機(jī)制詳解

    SpringBoot中的三種應(yīng)用事件處理機(jī)制詳解

    在項(xiàng)目開發(fā)中,組件間的松耦合設(shè)計(jì)至關(guān)重要,應(yīng)用事件處理機(jī)制作為觀察者模式的一種實(shí)現(xiàn),允許系統(tǒng)在保持模塊獨(dú)立性的同時(shí)實(shí)現(xiàn)組件間的通信,SpringBoot延續(xù)并增強(qiáng)了Spring框架的事件機(jī)制,提供了多種靈活的事件處理方式,本文給大家介紹了SpringBoot中的三種應(yīng)用事件處理機(jī)制
    2025-04-04
  • springboot添加多數(shù)據(jù)源的方法實(shí)例教程

    springboot添加多數(shù)據(jù)源的方法實(shí)例教程

    這篇文章主要給大家介紹了關(guān)于springboot添加多數(shù)據(jù)源方法的相關(guān)資料,在實(shí)際開發(fā)中經(jīng)??赡苡龅皆谝粋€(gè)應(yīng)用中可能要訪問多個(gè)數(shù)據(jù)庫多的情況,需要的朋友可以參考下
    2023-09-09
  • SpringBoot使用AOP切面對請求進(jìn)行日志記錄方式

    SpringBoot使用AOP切面對請求進(jìn)行日志記錄方式

    這篇文章主要介紹了SpringBoot使用AOP切面對請求進(jìn)行日志記錄方式,具有很好的參考價(jià)值,希望對大家有所幫助,如有錯(cuò)誤或未考慮完全的地方,望不吝賜教
    2025-05-05

最新評(píng)論

常德市| 海兴县| 吴忠市| 东阿县| 东至县| 宣城市| 双牌县| 鞍山市| 香港 | 宣汉县| 德格县| 都昌县| 大石桥市| 逊克县| 武乡县| 景宁| 宿州市| 清河县| 宁明县| 桐梓县| 包头市| 平舆县| 赤壁市| 永胜县| 元谋县| 巩留县| 西乡县| 承德市| 吴忠市| 汤原县| 芦山县| 密云县| 博野县| 德江县| 漠河县| 浑源县| 安岳县| 乌审旗| 东阿县| 始兴县| 娄底市|