MQ死信对列

面试题:你们是如何保证消息不丢失的?

1、什么是死信

死信就是消息在特定场景下的一种表现形式,这些场景包括:

  1. 消息被拒绝访问,即消费者返回 basicNack 的信号时 或者拒绝basicReject

2. 消费者发生异常,超过重试次数 。 ( 其实spring框架调用的就是 basicNack**)**

3.消息的Expiration 过期时长或队列TTL过期时间 。.ttl(20*1000) 进入的是 先进业务队列的数据.业务队列中先进入队列的信息会阻塞门口,不让过期的信息进入死信队列直到自己过期才放行,后期用rabbitmq的延时队列插件,实现同一个队列中有多个不同超时时间的消息,并按时间超时顺序出队

  1. 消息队列达到最大容量 .maxLength(5).先进业务队列的消息由死信交换机进入死信队列

述场景经常产生死信,即消息在这些场景中时,被称为死信

2、什么是死信队列

死信队列就是用于储存死信的消息队列,在死信队列中,有且只有死信构成,不会存在其余类型的消息。

死信队列在 RabbitMQ 中并不会单独存在,往往死信队列都会绑定这一个普通的业务消息队列,当所绑定的消息队列中,有消息变成死信了,那么这个消息就会重新被交换机路由到指定的死信队列中去,我们可以通过对这个死信队列进行监听,从而手动的去对这一消息进行补偿。 人工干预

3、那么,我们到底如何来使用死信队列呢?

只需要在声明业务队列的时候,绑定指定的死信交换机和RoutingKey即可。

死信交换机一般用直连交换机,将死信路由到指定的死信队列;业务则用广播交换机

消息队列达到最大容量;队列TTL过期时间

复制代码
@Configuration
public class OrderingOKConsumer {
    //死信交换机用直连
    @Bean
    public DirectExchange deadExchange() {
        return ExchangeBuilder.directExchange("ordering_ok_dlx").durable(true).build();
    }
//私信队列和正常没啥区别
    @Bean
    public Queue deadQueue() {
        return QueueBuilder.durable("ordering_ok_wms_dl").build();
    }
//死绑
    @Bean
    public Binding bindingDead() {
        return BindingBuilder.bind(deadQueue()).to(deadExchange()).with("ordering_ok_wms_dl");
    }
//业务交换机用广播
    @Bean
    public FanoutExchange exchange5() {
        return ExchangeBuilder.fanoutExchange("ordering_ok").durable(true).build();
    }
//业务队列,要和死信交换机和队列绑定
    @Bean
    public Queue queue5() {
        return QueueBuilder.durable("ordering_ok_wms").maxLength(3)
                .deadLetterExchange("ordering_ok_dlx")
                .deadLetterRoutingKey("ordering_ok_wms_dl")
                .ttl(10000)//设置队列过期时间
                .build();
    }

    @Bean
    public Binding binding5() {
        return BindingBuilder.bind(queue5()).to(exchange5());
    }

    //@RabbitListener(queues = "ordering_ok_wms")
    public void consumer(OrderingOk msg) {
        System.out.println("ordering_ok_wms收到消息:" + msg);
        int i = 1 / 0;
    }
}

消息的Expiration 过期时长

复制代码
@Service
public class OrderingOkProvider {
    @Autowired
    private RabbitTemplate rabbitTemplate;
    public void send(OrderingOk msg) {
        rabbitTemplate.convertAndSend("ordering_ok","",msg,message -> {
            Long id=msg.getId();
            int expire = 0;
            switch (id.intValue()){
                case 1:
                    expire = 50*1000;
                    break;
                case 2:
                    expire = 40*1000;
                    break;
                case 3:
                    expire = 30*1000;
                    break;
                case 4:
                    expire = 20*1000;
                    break;
                case 5:
                    expire = 10*1000;
                    break;
            }
             // message.getMessageProperties().setExpiration(expire+"");
            return message;
        });
    }
}

4. 自动应答死信配置

#-------------MQ 高级配置---------

#预抓取数量

spring.rabbitmq.listener.simple.prefetch=250

#设置消费者手动应答模式

spring.rabbitmq.listener.simple.acknowledge-mode = auto

#开启自动应答重试机制

spring.rabbitmq.listener.simple.retry.enabled=true

#默认重试3次

spring.rabbitmq.listener.simple.retry.max-attempts=3

#重试间隔时间 单位ms

spring.rabbitmq.listener.simple.retry.initial-interval=1000ms

#时间间隔倍数,默认是1倍

spring.rabbitmq.listener.simple.retry.multiplier=2

#最大间隔时间

spring.rabbitmq.listener.simple.retry.max-interval=5000ms

相关推荐
Bruce_Liuxiaowei22 分钟前
基于Python+Flask的MCP SDK响应式文档展示系统设计与实现
开发语言·python·flask·mcp
界面开发小八哥24 分钟前
Java开发工具IntelliJ IDEA v2025.1——全面支持Java 24、整合AI
java·ide·人工智能·intellij-idea·idea
chuxinweihui30 分钟前
数据结构——栈与队列
c语言·开发语言·数据结构·学习·算法·链表
我不是程序猿儿30 分钟前
[C#]反射的实战应用,实际数据模拟
开发语言·c#
wt_cs41 分钟前
身份证实名认证接口数字时代的信任基石-node.js实名认证集成
开发语言·node.js·php
普兰店拉马努金1 小时前
【高中数学/古典概率】4红2黑六选二,求取出两次都是红球的概率
java·概率
智商低情商凑1 小时前
CAS(Compare And Swap)
java·jvm·面试
yangmf20401 小时前
使用 Logstash 迁移 MongoDB 数据到 Easysearch
java·elasticsearch·搜索引擎
爱编程的鱼1 小时前
C# 结构(Struct)
开发语言·人工智能·算法·c#
Tiger_shl1 小时前
【Python语言基础】24、并发编程
java·数据库·python