RabbitMQ延迟队列(重要)

RabbitMQ延迟队列

1、延迟队列

https://blog.csdn.net/weixin_42942786/article/details/139940269

1.1、延迟队列使用场景

场景:有一个订单,15分钟内如果不支付,就把该订单设置为交易关闭,那么就不能支付了,这类实现延迟任务的场景就可以采用延迟队列来实现,当然除了延迟队列来实现,也可以有一些其他办法实现;

1.2、延迟队列实现原理

RabbitMQ本身不支持延迟队列,可以使用TTL(过期消息)结合DLX(死信交换机)的方式来实现消息的延迟投递,即把DLX(死信交换机)跟某个队列绑定,到了指定时间,消息过期后,就会从DLX(死信交换机)路由到这个队列,消费者可以从这个队列取走消息。

2、使用rabbitmq-delayed-message-exchange 延迟插件

2.1、下载

选择对应的版本下载 rabbitmq-delayed-message-exchange 插件,

下载地址:http://www.rabbitmq.com/community-plugins.html


2.2、安装

插件拷贝到 RabbitMQ 服务器plugins目录下

2.2.1、解压

java 复制代码
unzip rabbitmq_delayed_message_exchange-3.10.2.ez

如果unzip 没有安装,先安装一下

java 复制代码
yum install unzip -y

2.2.2、启用插件

java 复制代码
./rabbitmq-plugins enable rabbitmq_delayed_message_exchange 开启插件;

2.2.3、查询安装情况

./rabbitmq-plugins list 查询安装的所有插件;

重启rabbitmq使其生效;(此处也可以不重启)

消息发送后不会直接投递到队列,

而是存储到 Mnesia(嵌入式数据库),检查 x-delay 时间(消息头部);

延迟插件在 RabbitMQ 3.5.7 及以上的版本才支持,依赖 Erlang/OPT 18.0 及以上运行环境;

Mnesia 是一个小型数据库,不适合于大量延迟消息的实现

解决了消息过期时间不一致出现的问题。

2.4、示例

2.4.1、RabbitConfig配置类(关键代码)

java 复制代码
package com.power.config;

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

import java.util.HashMap;
import java.util.Map;

@Configuration
public class RabbitConfig {

    @Value("${my.exchangeName}")
    private String exchangeName;

    @Value("${my.queueDelayName}")
    private String queueDelayName;

    //创建自定义交换机
    @Bean
    public CustomExchange customExchange() {
        Map<String, Object> arguments = new HashMap<>();
        arguments.put("x-delayed-type","direct");
        return new CustomExchange(exchangeName,"x-delayed-message",true,false,arguments);
    }

    //创建队列
    @Bean
    public Queue queueNormal() {
        //建造者模式创建队列
        return QueueBuilder
                .durable(queueDelayName)//队列名称
                .build();
    }

    //队列绑定交换机
    @Bean
    public Binding binding(CustomExchange customExchange, Queue queueNormal) {
        return BindingBuilder.bind(queueNormal).to(customExchange).with("plugin").noargs();
    }

}

2.4.2、发送消息(关键代码)

java 复制代码
package com.power.service;

import lombok.extern.slf4j.Slf4j;
import org.springframework.amqp.core.Message;
import org.springframework.amqp.core.MessageBuilder;
import org.springframework.amqp.core.MessageProperties;
import org.springframework.amqp.rabbit.core.RabbitTemplate;
import org.springframework.context.annotation.Bean;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.util.Date;

@Service
@Slf4j
public class MessageService {

    @Resource
    private RabbitTemplate rabbitTemplate;

    @Bean
    public void sendMsg(){
        {
            MessageProperties messageProperties = new MessageProperties();
            messageProperties.setHeader("x-delay",25000);//第一条消息设置过期时间25秒
            Message message = MessageBuilder.withBody("hello world 01".getBytes())
                    .andProperties(messageProperties)
                    .build();
            rabbitTemplate.convertAndSend("exchange.delay.04","plugin",message);
            log.info("消息order发送完毕,发送时间是:{}",new Date());
        }
        {
            MessageProperties messageProperties = new MessageProperties();
            messageProperties.setHeader("x-delay",15000);//第二条消息设置过期时间15秒
            Message message = MessageBuilder.withBody("hello world 02".getBytes())
                    .andProperties(messageProperties)
                    .build();
            rabbitTemplate.convertAndSend("exchange.delay.04","plugin",message);
            log.info("消息pay发送完毕,发送时间是:{}",new Date());
        }

    }
}

2.4.3、application.yml配置类

java 复制代码
server:
  port: 8080
spring:
  application:
    name: delay-plugins-test01

  rabbitmq:
    host: 你的服务器IP
    port: 5672
    username: 你的账号
    password: 你的密码
    virtual-host: power

my:
  exchangeName: exchange.delay.04         # 交换机
  queueDelayName: queue.delay.04          # 正常队列

2.4.4、接收消息

java 复制代码
package com.power.message;

import lombok.extern.slf4j.Slf4j;
import org.springframework.amqp.core.Message;
import org.springframework.amqp.rabbit.annotation.RabbitListener;
import org.springframework.stereotype.Component;

import java.util.Date;

@Component
@Slf4j
public class ReceiveMessage {
    @RabbitListener(queues = "queue.delay.04")
    public void receiveMsg(Message message){
        String body = new String(message.getBody());
        log.info("接收到的消息为:{},接收时间为:{}",body,new Date());
    }
}

2.4.5、pom.xml

java 复制代码
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
  xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
  <modelVersion>4.0.0</modelVersion>

  <groupId>com.power</groupId>
  <artifactId>rabbit_07_delay04_plugins</artifactId>
  <version>1.0-SNAPSHOT</version>

  <name>rabbit_07_delay04_plugins</name>

  <properties>
    <maven.compiler.source>8</maven.compiler.source>
    <maven.compiler.target>8</maven.compiler.target>
    <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
  </properties>

  <parent>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-parent</artifactId>
    <version>2.6.13</version>
    <relativePath/>
  </parent>

  <dependencies>
    <dependency>
      <groupId>org.springframework.boot</groupId>
      <artifactId>spring-boot-starter-web</artifactId>
    </dependency>
    <dependency>
      <groupId>org.springframework.boot</groupId>
      <artifactId>spring-boot-starter-test</artifactId>
      <scope>test</scope>
    </dependency>
    <dependency>
      <groupId>org.projectlombok</groupId>
      <artifactId>lombok</artifactId>
      <version>1.18.24</version>
    </dependency>
    <dependency>
      <groupId>org.springframework.boot</groupId>
      <artifactId>spring-boot-starter-amqp</artifactId>
    </dependency>
  </dependencies>

  <build>
    <plugins>
      <plugin>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-maven-plugin</artifactId>
      </plugin>
    </plugins>
  </build>

</project>

2.4.6、测试

相关推荐
用户8307196840821 天前
RabbitMQ vs RocketMQ 事务大对决:一个在“裸奔”,一个在“开挂”?
后端·rabbitmq·rocketmq
初次攀爬者3 天前
RabbitMQ的消息模式和高级特性
后端·消息队列·rabbitmq
初次攀爬者5 天前
ZooKeeper 实现分布式锁的两种方式
分布式·后端·zookeeper
让我上个超影吧6 天前
消息队列——RabbitMQ(高级)
java·rabbitmq
塔中妖6 天前
Windows 安装 RabbitMQ 详细教程(含 Erlang 环境配置)
windows·rabbitmq·erlang
断手当码农6 天前
Redis 实现分布式锁的三种方式
数据库·redis·分布式
初次攀爬者6 天前
Redis分布式锁实现的三种方式-基于setnx,lua脚本和Redisson
redis·分布式·后端
业精于勤_荒于稀6 天前
物流订单系统99.99%可用性全链路容灾体系落地操作手册
分布式
Ronin3056 天前
信道管理模块和异步线程模块
开发语言·c++·rabbitmq·异步线程·信道管理
Asher05096 天前
Hadoop核心技术与实战指南
大数据·hadoop·分布式