RocketMQ基于延迟消息机制优化大量订单的定时退款扫描问题
1. 生产者设置延迟队列
public class ScheduledMessageProducer {
public static void main(String[] args) throws Exception {
// 创建一个订单系统的生产者实例,指定生产者组名为"OrderSystemProducerGroup"
DefaultMQProducer producer = new DefaultMQProducer("OrderSystemProducerGroup");
// 启动生产者
producer.start();
// 创建一个消息对象,消息主题为"CreateOrderInformTopic",消息体为订单信息的JSON串
Message message = new Message(
"CreateOrderInformTopic",
orderInfoJSON.getBytes()
);
// 设置消息为延迟消息,延迟级别为3,具体延迟时间取决于MQ配置
message.setDelayTimeLevel(16);
// 发送消息
producer.send(message);
}
}
其实发送延迟消息的核心,就是设置消息的delayTimeLevel,也就是延迟级别
RocketMQ默认支持一些延迟级别如下:1s 5s 10s 30s 1m 2m 3m 4m 5m 6m 7m 8m 9m 10m 20m 30m 1h 2h
上面代码中设置延迟级别为16,也就是对应上面的30分钟。
2. 消费者消费
public class ScheduledMessageConsumer {
public static void main(String[] args) throws Exception {
// 创建一个订单扫描服务的消费者实例,指定消费者组名为"OrderScanServiceConsumer"
DefaultMQPushConsumer consumer = new DefaultMQPushConsumer("OrderScanServiceConsumer");
// 订阅主题为"CreateOrderInformTopic"的所有消息(标签为空表示接收所有标签)
consumer.subscribe("CreateOrderInformTopic", "");
// 注册一个并发消息监听器
consumer.registerMessageListener(new MessageListenerConcurrently() {
@Override
public ConsumeConcurrentlyStatus consumeMessage(
List<MessageExt> messages, ConsumeConcurrentlyContext context) {
for (MessageExt message : messages) {
// 打印消息的存储时间到消费时间的差值
System.out.println("Receive message[" +
message.getMsgId() + "] " +
(System.currentTimeMillis() - message.getStoreTimestamp()) +
"ms later");
//业务逻辑处理 比如订单扫描服务,正常他会对每个订单创建的消息,在30分钟以后才获取到,然后去查询订单
// 状态,判断如果是未支付的订单,就自动关闭这个订单
}
// 返回消息消费成功状态
return ConsumeConcurrentlyStatus.CONSUME_SUCCESS;
}
});
// 启动消费者
consumer.start();
}
}