By Kaiyi and Mingduan
Since its development about a decade ago, Apache RocketMQ has been proven to be a stable solution for a wide variety of businesses. Now, it is widely implemented in Alibaba Group's internal processes and used by over tens of thousands of Alibaba Cloud enterprise users. As a messaging solution with financial-grade reliability, it has focused on building its asynchronous communication capacity in business integration.
This article introduces the scenarios where messaging services are integrated. It also describes the use cases, scenarios, and best practices of the scheduled messages feature in RocketMQ.
In the business message integration scenario, a scheduled message happens when the producer does not expect the message to be consumed by the consumer immediately after sending a message to the message queue. Instead, the producer expects the message to be consumed at a specified time.
The delayed message is another interpretation of the scheduled message, which means producers expect messages to be delayed for a certain period. It can be understood as scheduling to the current time with a certain delay.
Compare the process of scheduled messages and normal messages. Normal messages can be divided into message sending, message storage, and message consumption. After a message is sent to the topic, the message is immediately waiting for consumers to consume.
For scheduled/delayed messages, it can be understood as normal messages with the characteristic of scheduled delivery. After the producer sends a scheduled message, the message does not immediately enter the user's real topic but is temporarily stored in a system topic by RocketMQ. RocketMQ will deliver the message to the real topic at the specified time when consumers can consume it.
Accurate and reliable time-based event triggers are required in scenarios (such as distributed timed scheduling and task timeout processing). Such scheduled event triggers often have the following demands.
Traditional timed scheduling schemes are often implemented based on the task table scanning mechanism of the database. The general idea is to put the tasks that need to be triggered at a specified time into the database. Then, the micro-application regularly triggers the operation of scanning the database at a specified time to realize the task retrieval processing.
Although this type of solution can implement timed scheduling, it has many shortcomings.
RocketMQ's scheduled messages can simplify the development logic of timed scheduling tasks to achieve high performance, high scalability, and highly reliable timed triggering capabilities in this type of timed scheduling scenario.
Scheduled messages can be used to perform certain operations after a certain period without the business system managing the state of timing. The following describes a typical case: financial payment timeout. In an order system, we want to check the user's order status 30 minutes after the user places the order. If the user has not paid, the order will be automatically canceled.
Based on RocketMQ scheduled messages, we can send a scheduled message 30 minutes after the user places an order. We can set the order ID to MessageKey. After 30 minutes, the order system receives the message, and it can check the status of the order through the order ID. If the user hasn't paid yet, the order will be automatically closed.
As described earlier, the core of scheduled messages is how to transfer messages from the system's scheduled topic to the user topic at a specific time.
In Apache RocketMQ 4.x, scheduled messages are first placed in different queues of the SCHEDULE_TOPIC_XXXX system based on DelayLevel. Then, a scheduled task is started for each queue to pull messages regularly and transfer the messages that have reached the time to the user's topic. This is simple to implement, but only scheduled messages for specific DelayLevel are supported.
At present, pr, which supports the implementation of scheduled messages to any second, has been proposed in the community. The following part briefly introduces its basic implementation principles.
Before introducing the specific implementation principle, first, let’s learn the classic time wheel algorithm, which is the core algorithm of the scheduled message implementation.
As shown above, this is a time wheel with a lap timing of seven seconds, and the minimum granularity of timing is in seconds. There will be a pointer pointed at the current time on the time wheel, which will periodically move to the next scale.
Now, we want to set the time to one second later, and put the data into the 1 scale. If multiple data need to be set to the same time,
It will be added as a linked list. When the time is wheeled to the 1 scale, it will be read and dequeued from the linked list. How can we set the time to exceed one lap? For example, we want to set the time to 14 seconds. Since the time of one lap is seven seconds, we put it on the 6 scale. When it goes to 6 for the first time and the current time is found to be less than the expected time, this data is ignored. When it turns to 6 twice, we will see it has reached the expected 14 seconds.
In RocketMQ, TimerWheel is used to describe and store the time wheel, and an AppendOnly TimerLog is used to record all messages corresponding to each scale on the time wheel.
TimerLog records some important metadata of a scheduled message, which is used to transfer the message to the user's topic when it is the scheduled time. Here are several important attributes:
Name | Description |
size | Size of a Record |
prevPos | Point to the Previous Record |
magic | magic value |
delayTime | Scheduled Time |
offsetReal | The Offset of the Message in CommitLog |
sizeReal | The Size of the Message in CommitLog |
For TimerWheel, it can be abstracted as a fixed-length array. Each cell in the array represents a scale above the time wheel. A of TimerWheel scale has the following attributes.
Name | Description |
delayTime | Delay Time |
firstPos | The Location of the First TimerLog Record |
lastPos | The Location of the Last TimerLog Record |
The following figure shows the direct relationship between TimerWheel and TimerLog.
Each frame in TimerWheel represents a time scale. A firstPos points to the address of the first TimerLog record of all scheduled messages under this scale, and a lastPos points to the address of the last TimerLog record of all scheduled messages under this scale. In addition, for messages on the same scale, their TimerLog will be strung into a linked list through prevPos.
When you need to add a new record, add a 1-4. Then, point the prevPos of the new record to the current lastPos 1-3 and modify the lastPos to point to 1-4*. Then, all the TimerLog records on the same scale are strung together.
With TimerWheel and TimerLog, let's learn how a scheduled message is finally delivered to the user after it is sent to RocketMQ.
First of all, when it is found that the user is sending a scheduled message, RocketMQ will send the message to a system topic dedicated to processing scheduled messages.
There will be five services in the TimerMessageStore. The whole process can be divided into two stages: inbound time wheel and outbound time wheel.
Inbound Time Wheel:
Outbound Time Wheel:
After understanding the principle of the RocketMQ second-level scheduled message, let's learn how to use it. First, we need to create a scheduled/delayed message type of topic, which can be created using the console or the CLI command.
As shown in the preceding introduction, for scheduled messages, it is performing some operations when sending messages. So, producers can set the desired delivery time when sending rather than sending normal messages.
When it is nearly the scheduled time, this message is a normal message delivered to the user's topic. For consumers, it is no different from the consumption of normal messages.
Note: Scheduled messages are stored in a time-based storage system before they are delivered to consumers at the specified delivery time. If you specify the same delivery time for many scheduled messages, the system has to simultaneously process the messages at the delivery time. This puts the system under heavy load and results in delays in message delivery. Therefore, it is recommended not to set a large number of messages at the same time.
Deploying your OAM Applications in the Napptive Cloud-native Application Platform
Use Transactional Messages to Understand RocketMQ Service Messages
508 posts | 48 followers
FollowAlibaba Cloud Native Community - January 31, 2023
Alibaba Cloud Native Community - December 19, 2022
Alibaba Cloud Community - December 21, 2021
Alibaba Cloud Native - June 7, 2024
Alibaba Cloud Native - August 6, 2024
Alibaba Cloud Native - June 11, 2024
508 posts | 48 followers
FollowApsaraMQ for RocketMQ is a distributed message queue service that supports reliable message-based asynchronous communication among microservices, distributed systems, and serverless applications.
Learn MoreReach global users more accurately and efficiently via IM Channel
Learn MoreAlibaba Cloud Function Compute is a fully-managed event-driven compute service. It allows you to focus on writing and uploading code without the need to manage infrastructure such as servers.
Learn MoreA one-stop cloud service for global voice communication
Learn MoreMore Posts by Alibaba Cloud Native Community