延迟消息
延迟消息:生产者发送消息时指定一个时间,消费者不会立刻收到消息,而是在指定时间之后才收到消息。
延时任务: 设定在一定时间之后才执行的任务
如果你们业务不使用消息队列中间件,也可以使用redis,具体方式参考:
https://blog.csdn.net/qq_42875345/article/details/108428495
死信交换机
当一个队列中的消息满足下列情况之一时,就会成为死信(dead letter):
- 消费者使用basic.reject或basic.nack声明消费失败,并且消息的requeue参数设置为false
- 消息是一个过期消息(达到了队列或消息本身设置的过期时间),超时无人消费
- 要投递的队列消息堆积满了,最早的消息可能成为死信。
如果队列通过dead-letter-exchange属性指定了一个交换机,那么该队列中的死信就会投递到这个交换机中,这个交换机称为死信交换机(Dead Letter Exchange,简称DLX).
@Test
public void simpleQueueExp(){
// Message message = MessageBuilder.withBody("阴风瑞丽敌胆寒".getBytes(StandardCharsets.UTF_8)).setExpiration("30000").build();
rabbitTemplate.convertAndSend("simple.direct", "simple", "丧家之犬,主公实不足虑也", message1 -> {
message1.getMessageProperties().setExpiration("10000");
return message1;
});
log.info("消息发送成功");
}
延迟消息插件
RabbitMQ的官方也推出了一个插件,原生支持延迟消息功能。该插件的原理是设计了一种支持延迟消息功能的交换机,当消息投递到交换机后可以暂存一定时间,到期后再投递到队列。
1.在虚拟机上执行docker inspect mq找到本地挂载的数据卷。
2.进入数据卷目录,上传延迟插件
3.执行以下命令加载延迟消息插件
docker exec -it mq rabbitmq-plugins enable rabbitmq_delayed_message_exchange
4.使用方式
@RabbitListener(bindings = @QueueBinding(value = @Queue(value = "delay.queue",durable = "true"),exchange = @Exchange(name = "delay.direct",delayed = "true"),key = {"delay"}))
public void listenDelayMessage(String msg){
log.info("接收到delay.queue的延迟消息:{}",msg);
}
@Test
public void delayQueue(){
rabbitTemplate.convertAndSend("delay.direct","delay","见微知著,识人心智",message -> {
message.getMessageProperties().setDelay(30000);
return message;
});
log.info("神郭嘉");
}
会给服务器带来压力,特别是当延迟时间设置特别长时。适用于延时时间相对比较短的场景。
取消超时订单
设置30分钟后检测订单支付状态实现起来非常简单,但是存在两个问题:
- 如果并发较高,30分钟可能堆积消息过多,对MQ的压力很大
- 大多数订单在下单后一分钟内就会支付,但是却需要在MQ中等待30分钟,浪费资源