RocketMQ advanced-delayed message

 

 

Preface

In the development, we often encounter the need for delayed tasks. For example, if you buy a ticket at 12306, if the order is not paid within 30 minutes, it will be automatically cancelled; and the online mall will not evaluate the order for 48 hours after completing the order, and will automatically receive a 5-star rating. Demand tasks such as execution over a period of time after a trigger event which we call delay task .

So how to realize the delayed task?

The first reaction is to use the cron scheme to achieve:

Start a cron timed task and execute it every once in a while, for example, 30 minutes, find the timeout data, directly update the status, or take it out to perform some operations. If the amount of data is relatively large, paging query and paging update are required, which will be a for loop update operation.

The cron scheme is a very common scheme, but the common one is not necessarily the best. There are mainly the following problems:

  • When the amount of data is large, the polling efficiency is low;

  • The timeliness is not good enough, if polling once every hour, the worst case time error will reach 1 hour;

  • If the cron polling frequency is increased to reduce the time error, the polling inefficiency and double calculation problems will occur;

Since the cron solution is not ideal, please ask our protagonist today and use RocketMQ's delayed message to solve it. When an order is created, a delayed message is sent to RocketMQ. After 30 minutes, the consumer consumes the message to check the status of the order. If the order is found to be unpaid, the order is cancelled and the inventory is released.

achieve

The core idea of ​​RocketMQ delay queue is: after all delayed messages are sent by the producer, they will be stored in the same topic (SCHEDULE_TOPIC_XXXX), and different delay levels will correspond to different queue numbers. When the delay time expires, they will be read by the timing thread. It is converted to a common message and stored under the real specified topic. At this time, the message is visible to the consumer and consumed by the consumer.

Note: RocketMQ does not support any time delay, only the following fixed delay levels
private String messageDelayLevel = "1s 5s 10s 30s 1m 2m 3m 4m 5m 6m 7m 8m 9m 10m 20m 30m 1h 2h";

Next, we use RocketMQ to send delayed messages in combination with SprintBoot

  • Introduce RocketMQ components

<dependency>
 <groupId>org.apache.rocketmq</groupId>
 <artifactId>rocketmq-spring-boot-starter</artifactId>
</dependency>
  • Increase the configuration of RocketMQ

rocketmq:
  name-server: 172.31.0.44:9876
  producer:
    group: delay-group
  • Write producer

@Component
@Slf4j
public class DelayProduce {
    @Autowired
    private RocketMQTemplate rocketMQTemplatet;

    public void sendDelayMessage(String topic,String message,int delayLevel){
       SendResult sendResult = rocketMQTemplatet.syncSend(topic, MessageBuilder.withPayload(message).build(), 2000, delayLevel);
        log.info("sendtime is {}", DateTimeFormatter.ofPattern("yyyy年MM月dd日 HH:mm:ss").format(LocalDateTime.now()));
        log.info("sendResult is{}",sendResult);
    }
}
  • Write consumer

@Slf4j
@Component
@RocketMQMessageListener(
        topic = "delay-topic",
        consumerGroup = "delay-group"
)
public class DelayConsumer implements RocketMQListener<String> {
    @Override
    public void onMessage(String message) {
        log.info("received message time is {}", DateTimeFormatter.ofPattern("yyyy年MM月dd日 HH:mm:ss").format(LocalDateTime.now()));
        log.info("received message is {}",message);
    }
}
  • test

@RunWith(SpringRunner.class)
@SpringBootTest
public class DelayProduceTest {
    @Autowired
    private DelayProduce delayProduce;

    @Test
    public void sendDelayMessage() {
        delayProduce.sendDelayMessage("delay-topic","Hello,JAVA日知录",5);
    }
}

Here delayLevel is set to 5, corresponding to RocketMQ's delay level is to deliver the message after 1 minute.

  • Running result sending time consumption time

Modify the delay level

The delay level of RocketMQ can be modified to meet your own business needs, and you can modify/add new levels. For example: if you want to support a 1-day delay, modify the value of the last level to 1d, this time is still 18 levels; you can also add a 1d, this time there are 19 levels in total.

  • Open RocketMQ configuration files, modify messageDelayLevelattributes

brokerClusterName = DefaultCluster
brokerName = broker-a
brokerId = 0
deleteWhen = 04
fileReservedTime = 48
brokerRole = ASYNC_MASTER
flushDiskType = ASYNC_FLUSH
storePathRootDir = /app/rocketmq/data
messageDelayLevel=90s 5s 10s 30s 1m 2m 3m 4m 5m 6m 7m 8m 9m 10m 20m 30m 1h 2h

This time the delay level 1 is changed to 90s, and the producer needs 90s to deliver the message after sending the message. Restart RocketMQ after modification.nohup sh mqbroker -n localhost:9876 -c ../conf/broker.conf &

  • Send message using delay level 1

public void sendDelayMessage() {
 delayProduce.sendDelayMessage("delay-topic","Hello,JAVA日知录",1);
}
  • Test sending time consumption time

It is proved that the delay level modification takes effect by comparing the sending time and the consumption time.

RocketMQ related articles

Well, friends, this is the end of the content of this issue. You can see that the students here are all excellent students. The next promotion and salary increase is you!
If you think this article is helpful to you, please scan the QR code below and pay attention. "Forward" and "watching", develop a good habit! See you next time!

 

Hot article recommendation

http://www.javadaily.cn

 

Guess you like

Origin blog.csdn.net/jianzhang11/article/details/106247790