7 Common Message Queue Scenarios and Their Implementations
This article explains seven typical message‑queue use cases—including ordinary, ordered, delayed, transactional, trace, dead‑letter, and priority messages—detailing their business motivations, implementation challenges, and concrete code examples for Kafka, RocketMQ, Pulsar, and RabbitMQ.
Hello, I am Wukong. When selecting a message‑queue solution we usually consider the business scenario. Below are seven common message scenarios and how they are implemented in mainstream MQ products.
1. Ordinary Message
The basic function of a message queue is to let producers send messages, brokers store them, and consumers retrieve them, achieving system decoupling and peak‑shaving.
2. Ordered Message
Ordered messages require the sending order of the producer to match the consumption order of the consumer, e.g., order creation → payment → shipment in e‑commerce.
Challenges include multiple producers, multiple partitions, and concurrent consumers, which can break ordering.
To guarantee order, two conditions must be met:
The same producer must synchronously send messages to the same partition.
A partition can be consumed by only one consumer.
Kafka and Pulsar assign a key to each message and hash it to a partition. RocketMQ can use MessageQueueSelector to choose a queue:
public static void main(String[] args) throws UnsupportedEncodingException {
try {
DefaultMQProducer producer = new DefaultMQProducer("please_rename_unique_group_name");
producer.start();
String[] tags = new String[]{"TagA", "TagB", "TagC", "TagD", "TagE"};
for (int i = 0; i < 100; i++) {
int orderId = i % 10;
Message msg = new Message("TopicTestjjj", tags[i % tags.length], "KEY" + i,
("Hello RocketMQ " + i).getBytes(RemotingHelper.DEFAULT_CHARSET));
SendResult sendResult = producer.send(msg, new MessageQueueSelector() {
@Override
public MessageQueue select(List<MessageQueue> mqs, Message msg, Object arg) {
Integer id = (Integer) arg;
int index = id % mqs.size();
return mqs.get(index);
}
}, orderId);
System.out.printf("%s%n", sendResult);
}
producer.shutdown();
} catch (MQClientException | RemotingException | MQBrokerException | InterruptedException e) {
e.printStackTrace();
}
}RabbitMQ uses an exchange and a routing key to route messages:
@Resource
private AmqpTemplate rabbitTemplate;
public void send1(String message) {
rabbitTemplate.convertAndSend("testExchange", "testRoutingKey", message);
}3. Delayed (Scheduled) Message
Delayed messages are not consumed immediately but after a specified time, e.g., canceling an unpaid order after 30 minutes.
3.1 RocketMQ Implementation
RocketMQ defines 18 delay levels; level 3 corresponds to a 10‑second delay.
private String messageDelayLevel = "1s 5s 10s 30s 1m 2m 3m 4m 5m 6m 7m 8m 9m 10m 20m 30m 1h 2h";Messages are first stored in a special topic (SCHEDULE_TOPIC_XXXX) and later moved to the original queue when the delay expires.
3.2 Pulsar Implementation
Pulsar stores delayed messages in a Delayed Message Tracker, which builds a priority queue based on the delay time. Consumers check the tracker for expired messages before pulling.
3.3 RabbitMQ Implementation
RabbitMQ can implement delayed messages either by routing expired messages to a dead‑letter queue or by storing them in a local Mnesia database and publishing them later.
3.4 Kafka Implementation
Kafka does not have a native delay queue, but delayed delivery can be achieved with producer interceptors or by using a dedicated delay topic.
4. Transactional Message
Transactional messages ensure that producing and consuming messages obey transaction semantics.
RabbitMQ and Kafka support producer‑side transactions (all‑or‑nothing send). RabbitMQ uses a channel to start a transaction:
ConnectionFactory factory = new ConnectionFactory();
connection = factory.newConnection();
Channel channel = connection.createChannel();
// start transaction
channel.txSelect();
channel.basicPublish("directTransactionExchange", "transactionRoutingKey", null, message.getBytes("utf-8"));
// commit or rollback
channel.txCommit();Kafka can assign the same transaction ID to multiple producers, allowing atomic writes across topics and partitions.
Pulsar defines a transaction that can encompass consume‑process‑produce as a single atomic operation.
RocketMQ implements transactional messages using half messages; it guarantees atomicity between the local transaction and the message send, but not consumer‑side atomicity.
5. Trace Message
Trace messages record the lifecycle of a message to help diagnose loss. They require storage and query capabilities and should not impact normal message performance.
RabbitMQ can enable tracing to send trace data to the amq.rabbitmq.trace exchange. RocketMQ also supports trace messages but they are disabled by default.
6. Dead‑Letter Queue
Dead‑letter queues handle abnormal situations such as rejected messages, expiration, or queue length limits.
RocketMQ provides a consumer‑side dead‑letter queue after 16 failed retries. RabbitMQ supports both producer‑ and broker‑side dead‑letter queues, routing messages to a dead‑letter exchange.
7. Priority Message
Some business scenarios require higher‑priority processing, e.g., premium customers in banking.
RabbitMQ supports priority queues:
ConnectionFactory factory = new ConnectionFactory();
connection = factory.newConnection();
Channel channel = connection.createChannel();
Map
args = new HashMap
();
// set max priority to 5
args.put("x-max-priority", 5);
channel.queueDeclare("my-priority-queue", true, false, false, args);8. Summary
When choosing a message‑queue solution, consider business scenarios, operational complexity, scale, community activity, and learning cost. The seven scenarios above provide a practical guide for selecting and configuring the right MQ technology.
Wukong Talks Architecture
Explaining distributed systems and architecture through stories. Author of the "JVM Performance Tuning in Practice" column, open-source author of "Spring Cloud in Practice PassJava", and independently developed a PMP practice quiz mini-program.
How this landed with the community
Was this worth your time?
0 Comments
Thoughtful readers leave field notes, pushback, and hard-won operational detail here.