MQ根据正常队列、死信队列来实现延迟队列的场景
1、在RabbitMQ的管理后台新建交换机(exchange);
名称(Name): **ParkingExchange**
类型(Type): **fanout**
持久化(Durability): **Durable**
2、在RabbitMQ的管理后台新建队列(queue);
名称(Name): **ParkingQueue**
类型(Type): **Classic**(新版本RabbitMQ需要选)
持久化(Durability): **Durable**
参数设置(Arguments):
x-message-ttl = 3000(点下边的Message TTL)
x-dead-letter-exchange = Ump_mq(点下边的Dead letter exchange, 然后填写Ump_mq)
3、在RabbitMQ的管理后台设置交换机**ParkingExchange**的Binding中的**To Queue**为**ParkingQueue**;
4、以上设置了队列ParkingQueue, 其消息的生命周期为3000毫秒, 即进入此队列的消息3秒会死掉, 死掉的消息会进去dead-letter-exchange为Ump_mq的交换机, 也就是实现了3秒延迟的后半部分.
总结:
正常队列A、死信队列B进行绑定;
当数据放入死信队列B,并设置过期时间,数据过期之后,数据会从死信队列B重新放入正常队列A,此时监听器(正常队列A)会监听到消息并消费当前数据;
代码示例:
public void pushOrderWxPayDelayData(Long orderId,Long orgId){ //正常队列的key String routingKey = "klota3.0.order.wx.ispay.key.*.*"; //死信队列的名称 String delayQueueName = "mq-clota-order-wx-ispay-delay-queue"; //死信队列的Key String delayQueueKey = "klota3.0.order.wx.ispay.delay.key.*.*"; try { //1、将当前正常队列与死信队列绑定 rabbitMqManager.declareAndBindQueue(new TopicExchange("mq-clota-notice-topic-exchange"), 10, "mq-clota-notice-topic-exchange",routingKey, Collections.singletonMap(delayQueueName, delayQueueKey)); } catch (Exception e) { e.printStackTrace(); } Map<String, Object> headerMap = new HashMap<>(); headerMap.put("orderId", orderId); headerMap.put("orgId", orgId); MqSyncVo mqSyncVo = new MqSyncVo(); mqSyncVo.setMessageId(String.valueOf(orderId)); mqSyncVo.setSyncType(String.valueOf(orgId)); /** 推送消息 **/ Long seconds = 30L; String obj = redisUtil.getValue(String.format(RedisKeys.ORDER_WX_ISPAY_COUNT_KEY, orderId, orgId)); //当前死信队列的key,当前key与上方 delayQueueKey klota3.0.order.wx.ispay.delay.key.*.* 能匹配上 String delayRoutingKey = "klota3.0.order.wx.ispay.delay.key.016.909"; //2、将数据推送到死信队列,30S后过期,30S后过期的数据会从死信队列返回到正常队列,则正常队列中监听到数据会进行消费,则根据正常队列、死信队列来实现了延迟队列的场景 rabbitMqManager.sendJsonMsgForTranAfterCommit(RabbitMqConst.NOTICE_TOPIC_EXCHANGE, delayRoutingKey, mqSyncVo, headerMap, Duration.ofSeconds(30L), Boolean.FALSE, null); }