RabbitMQ的死信队列、延迟队列、消息的幂等性消费

死信队列、延迟队列、消息的幂等性消费

一、通过代码实现创建队列和交换机以及绑定

  1. application.yml
# 端口号
server:
  port: 8083

# rabbitmq配置
spring:
  rabbitmq:
    host: 192.168.31.129
  1. 代码实现
package com.hong.config;

import org.springframework.amqp.core.*;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

/**
 * @Author hongCheng
 * @Date 2021/4/22 18:58
 * @Version 1.0
 */
@Configuration
public class RabbitConfig {

    private final String QUEUE = "myqueue03";//定义一个队列的名字
    private final String EXCHANGE = "myexchange03";//定义一个交换机的名字

    /**
     * 创建交换机
     *      directExchange 路由交换机模式
     *      durable 是否持久化
     * @return
     */
    @Bean
    public Exchange exchange(){
        return ExchangeBuilder.directExchange(EXCHANGE).durable(true).build();
    }

    /**
     * 创建队列
     *      durable 队列的名字
     *      withArgument(key,value):
     *          key:参数的名字
     *          value:参数的值
     * @return
     */
    @Bean
    public Queue queue(){
        return QueueBuilder.durable(QUEUE).withArgument("x-message-ttl",20000).build();
    }

    /**
     * 绑定
     * bind(queue()).to(exchange()) 将队列绑定到交换机上
     * with("") 如果没有路由,可以不写
     * noargs() 无参
     * @return
     */
    @Bean
    public Binding binding(){
        return BindingBuilder.bind(queue()).to(exchange()).with("").noargs();
    }
}
  1. 结果
    在这里插入图片描述

在这里插入图片描述

二、死信队列

​ 死信队列,英文缩写:DLX Dead Letter Exchange(死信交换机),当消息称为Dead message后,可以被重新发送到另一个交换机,这个交换机就是DLX。

在这里插入图片描述

消息称为死信的三种情况:

​ 1.队列消息长度到达限制;

​ 2.消费者拒接消息,basicNack/basicReject,并且不将消息重新放入到原目标队列,requeue=false;

​ 3.原队列存在消息过期设置,消息到达超时时间违背消费。
在这里插入图片描述

队列绑定死信交换机

给队列设置参数:x-dead-letter-exchange和x-dead-letter-routing-key

代码实现:

package com.hong.product;

import org.springframework.amqp.core.*;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

/**
 * @Author hongCheng
 * @Date 2021/4/22 15:42
 * @Version 1.0
 */
@Configuration
public class ProductConfig {

    private final String QUEUE = "myqueue03";
    private final String DEAD_QUEUE = "dead_queue";
    private final String EXCHANGE = "exchange";
    private final String DEAD_EXCHANGE = "dead_exchange";

    /**
     * 创建队列
     *  durable 队列的名字
     *  withArgument(key,value)
     * 		key	参数的名字
     *		value 参数的值
     * @return
     */
    @Bean
    public Queue queue(){
        return QueueBuilder.durable(QUEUE)
                .withArgument("x-message-ttl",30000)//设置参数的超时时间
                .withArgument("x-max-length",20)//参数的最多数量
                .withArgument("x-dead-letter-exchange",DEAD_EXCHANGE)//与死信交换机绑定关系
                .withArgument("x-dead-letter-routing-key","error")//设置路由
                .build();
    }

    /**
     * 创建死信队列
     * @return
     */
    @Bean
    public Queue dead_queue(){
        return QueueBuilder.durable(DEAD_QUEUE).build();
    }

    /**
     * 创建交换机
     * @return
     */
    @Bean
    public Exchange exchange(){
        return ExchangeBuilder.directExchange(EXCHANGE).build();
    }

    /**
     * 创建死信交换机
     * @return
     */
    @Bean
    public Exchange dead_exchange(){
        return ExchangeBuilder.directExchange(DEAD_EXCHANGE).build();
    }

    /**
     * 将普通交换机跟普通队列绑定
     * @return
     */
    @Bean
    public Binding binding(){
        return BindingBuilder.bind(queue()).to(exchange()).with("error").noargs();
    }

    /**
     * 将死信队列与死信交换机绑定
     * @return
     */
    @Bean
    public Binding dead_binding(){
        return BindingBuilder.bind(dead_queue()).to(dead_exchange()).with("error").noargs();
    }
}

在测试类中写一个类显示结果;

package com.hong;

import org.junit.jupiter.api.Test;
import org.springframework.amqp.rabbit.core.RabbitTemplate;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;

/**
 * @Author hongCheng
 * @Date 2021/4/22 20:13
 * @Version 1.0
 */
@SpringBootTest
public class ProduceTest {

    @Autowired
    private RabbitTemplate rabbitTemplate;

    /**
     * 测试死信队列
     */
    @Test
    public void testDeadExchange(){
        /**
         * String exchange, 交换机名字
         * String routingKey, 路由密钥
         * final Object object 信息
         */
        rabbitTemplate.convertAndSend("exchange","error","多喝热水");
    }
}

结果显示:
在这里插入图片描述

20秒后,时间达到之后进入到死信队列:
在这里插入图片描述

三、延迟队列

延迟队列:就是消息进入队列后不会立即被消费,只有达到指定事件后,才会被消费

实现方式:

  1. 定时器
  2. 延迟队列

在rabbitmq中并未提供延迟队列的功能

可以使用TTL+死信队列组和实现延迟队列的效果

将延迟队列设置过期时间30分钟,就比如订单,如果你没有支付订单,订单会给你保留一定的时间,时间一到就会自动默认为取消订单。
在这里插入图片描述

四、消息幂等性保障

幂等性指一次性和多次请求某一个资源,对于资源本身应该具有同样的结果。也就是说,其任意多次执行对资源本身所产生的影响均与依次执行的影响相同。

可以保证消息不被重复消费

  1. 消费者获取到信息后先根据id(唯一标识)去查询redis/db中是否存在该消息
  2. 如果不存在,则正常消费,消费完毕后写入redis/db中
  3. 如果存在,则证明消息被消费过,直接丢弃。
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值