8 Real-World MQ Use Cases Every Backend Engineer Should Know
This article explores eight practical scenarios for using message queues—such as asynchronous processing, service decoupling, traffic shaping, delayed tasks, log collection, distributed transactions, remote calls, and broadcast notifications—providing code examples with RabbitMQ, RocketMQ, and Kafka to illustrate each pattern.
Preface
Hello, I'm San You.
In daily development we often interact with MQ (message queues). This article summarizes eight MQ usage scenarios.
1. Asynchronous Processing
Interviewers often mention asynchronous processing, decoupling, traffic shaping when asking about MQ.
One of the most common MQ applications is asynchronous processing.
For example, in a user registration scenario, after the user information is saved, the system needs to send an SMS or email to notify the user. If sending the message is time‑consuming, it may block the registration interface. Using MQ for asynchronous processing prevents the notification from affecting the main registration flow.
Brief code:
<code>// User registration method
public void registerUser(String username, String email, String phoneNumber) {
// Save user info (simplified)
userService.add(buildUser(username,email,phoneNumber));
// Build message
String registrationMessage = "User " + username + " has registered successfully.";
// Send message to queue
rabbitTemplate.convertAndSend("registrationQueue", registrationMessage);
}
</code>Consumer reads the message from the queue and sends SMS or email:
<code>@Service
public class NotificationService {
// Listen to the queue and send SMS/email
@RabbitListener(queues = "registrationQueue")
public void handleRegistrationNotification(String message) {
// Send SMS
sendSms(message);
// Send email
sendEmail(message);
}
}
</code>2. Decoupling
In micro‑service architectures services need to communicate. Using MQ helps decouple services and avoids tight coupling.
An e‑commerce platform’s inventory service and payment service: after payment succeeds, the payment service sends a message to deduct inventory via MQ instead of calling the inventory API directly.
Payment service sends a message to RocketMQ:
<code>import org.apache.rocketmq.client.producer.DefaultMQProducer;
import org.apache.rocketmq.common.message.Message;
public class PaymentService {
private DefaultMQProducer producer;
public PaymentService() throws Exception {
producer = new DefaultMQProducer("PaymentProducerGroup");
producer.setNamesrvAddr("localhost:9876");
producer.start();
}
public void processPayment(String orderId, int quantity) throws Exception {
boolean paymentSuccessful = callPayment(orderId, quantity);
if (paymentSuccessful) {
String messageBody = "OrderId: " + orderId + ", Quantity: " + quantity;
Message message = new Message("paymentTopic", "paymentTag", messageBody.getBytes());
producer.send(message);
}
}
}
</code>Inventory service consumes the message:
<code>public class InventoryService {
private DefaultMQPushConsumer consumer;
public InventoryService() throws Exception {
consumer = new DefaultMQPushConsumer("InventoryConsumerGroup");
consumer.setNamesrvAddr("localhost:9876");
consumer.subscribe("paymentTopic", "paymentTag");
consumer.registerMessageListener((msgs, context) -> {
for (MessageExt msg : msgs) {
String messageBody = new String(msg.getBody());
reduceStock(messageBody);
}
return null;
});
consumer.start();
}
}
</code>3. Traffic Shaping
In high‑concurrency scenarios, sudden traffic spikes can overload services. MQ can be used to smooth traffic.
Ticket purchasing during Chinese New Year travel (12306).
Double‑12 shopping festival order surge.
Flash‑sale (秒杀) spikes.
Using MQ to limit processing to the system’s capacity (e.g., 2k requests per second) while buffering excess requests.
Example: a flash‑sale system can pull at most 2k requests per second from the queue even if 5k arrive.
4. Delayed Tasks
In an e‑commerce order flow, if an order is not paid within a certain time it should be automatically cancelled. MQ’s delayed‑queue feature can schedule a message to be consumed after the timeout.
Order service sends a delayed message to RocketMQ:
<code>@Service
public class OrderService {
@Autowired
private RocketMQTemplate rocketMQTemplate;
public void createOrder(Order order) {
long delay = order.getTimeout(); // milliseconds
rocketMQTemplate.syncSend(
"orderCancelTopic:delay" + delay,
MessageBuilder.withPayload(order).build(),
10000,
(int) (delay / 1000)
);
}
}
</code>Note: RocketMQ supports fixed delay levels (1 s, 5 s, 10 s, etc.). If the required delay does not match a level, choose the nearest level or adjust business logic.
Consumer for delayed messages:
<code>@Component
@RocketMQMessageListener(topic = "orderCancelTopic", consumerGroup = "order-cancel-consumer-group")
public class OrderCancelListener implements RocketMQListener<Order> {
@Override
public void onMessage(Order order) {
System.out.println("Cancelling order: " + order.getOrderId());
// cancel order logic...
}
}
</code>5. Log Collection
Message queues are often used to forward application logs to a centralized logging system.
Example using Kafka:
<code>// Producer sending logs to Kafka topic "app-logs"
KafkaProducer<String, String> producer = new KafkaProducer<>(config);
String logMessage = "{\"level\": \"INFO\", \"message\": \"Application started\", \"timestamp\": \"2024-12-29T20:30:59\"}";
producer.send(new ProducerRecord<>("app-logs", "log-key", logMessage));
</code> <code>@Service
public class LogConsumer {
@KafkaListener(topics = "app-logs", groupId = "log-consumer-group")
public void consumeLog(String logMessage) {
System.out.println("Received log: " + logMessage);
}
}
</code>6. Distributed Transactions
MQ is frequently used to implement distributed transactions.
Typical flow of a normal MQ message:
Producer sends message to MQ server.
MQ persists the message.
MQ returns ACK to producer.
MQ pushes the message to consumer.
Consumer processes and returns ACK.
MQ deletes the message after ACK.
In an order‑creation scenario, a half‑transaction message can be used so that the order is only visible to downstream services after the local transaction commits.
Producer sends a half‑transaction message.
MQ stores it with “pending” status.
MQ ACKs the producer without delivering.
Producer executes local transaction.
Producer commits or rolls back the message.
MQ updates the message status accordingly.
If committed, MQ pushes the message to consumers.
If MQ does not receive commit/rollback for a long time, it queries the producer to decide the final state.
7. Remote Invocation
Based on RocketMQ, a custom remote‑call framework was built for financial scenarios, providing features such as message query, multi‑center active‑active, gray release, traffic weighting, deduplication, and back‑pressure.
8. Broadcast Notifications
Message queues can broadcast events to multiple subscribers, e.g., system announcements or event‑driven notifications like order payment success.
System notifications: application updates, maintenance alerts. Event‑driven notifications: inventory update, user status change, payment success.
When an order payment succeeds, the event is sent via MQ and consumed by inventory, points, and finance systems.
<code>// Create order payment success event
String orderEventData = "{\"orderId\": 12345, \"userId\": 67890, \"amount\": 100.0, \"event\": \"ORDER_PAYMENT_SUCCESS\"}";
Message msg = new Message("order_event_topic", "order_payment_success", orderEventData.getBytes());
producer.send(msg);
</code>Inventory consumer example:
<code>consumer.registerMessageListener((MessageListenerConcurrently) (msgs, context) -> {
for (Message msg : msgs) {
String eventData = new String(msg.getBody());
System.out.println("Inventory system received: " + eventData);
// update inventory...
}
return ConsumeConcurrentlyStatus.CONSUME_SUCCESS;
});
</code>Points consumer and finance consumer follow a similar pattern.
Sanyou's Java Diary
Passionate about technology, though not great at solving problems; eager to share, never tire of learning!
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.