一句话总结
引入MQ的三大原因:解耦、异步、削峰。选型:RabbitMQ灵活延迟低适合中小系统,Kafka吞吐量极高适合日志/大数据,RocketMQ事务消息支持好适合金融级业务。
初级理解
引入MQ的原因:
• 解耦:生产者与消费者无需感知对方存在
• 异步:非核心链路异步处理,缩短主流程响应时间
• 削峰:缓冲突发流量,保护下游系统
三大MQ特点对比:
• RabbitMQ:灵活的路由机制(Exchange),延迟低,适合业务复杂的中小规模系统
• Kafka:极高的吞吐量,基于磁盘顺序写,适合日志收集、大数据流处理
• RocketMQ:阿里开源,原生支持事务消息、延迟消息、死信队列,适合金融级业务
一句话总结:RabbitMQ灵活,Kafka高吞吐,RocketMQ事务支持好。
中级深入
保证消息不丢失的三道防线:
1. 生产者端:开启Confirm机制(RabbitMQ)或同步发送+重试(RocketMQ)
2. Broker端:开启消息持久化(队列持久化 + 消息持久化)
3. 消费者端:关闭自动ACK,业务处理成功后手动ACK
消息重复消费处理:
消费者必须保证幂等性:
• 数据库唯一索引
• Redis Token机制
• 状态机校验
注意:消息重复消费是MQ的固问题,只能通过消费者幂等性来解决。
高级拓展
选型决策树:
是否需要事务消息? → 是 → RocketMQ
是否需要极高吞吐量? → 是 → Kafka
业务是否复杂(路由规则多)? → 是 → RabbitMQ
对延迟要求是否极高? → 是 → RabbitMQ
以上都不是 → RocketMQ(综合能力最强)
各MQ适用场景:
• RabbitMQ:订单状态通知、积分发放、邮件发送
• Kafka:日志收集、用户行为追踪、大数据分析
• RocketMQ:订单创建与支付、库存扣减、金融交易
面试加分项:能说出三道防线、幂等性方案、选型决策树,说明你对MQ有实战经验。
实战场景
场景:订单创建与库存扣减
// 生产者:订单服务
@Service
public class OrderProducer {
@Autowired
private RabbitTemplate rabbitTemplate;
public void createOrder(OrderDTO order) {
rabbitTemplate.convertAndSend("order-exchange", "order.create", order, message -> {
message.getMessageProperties().setDeliveryMode(MessageDeliveryMode.PERSISTENT);
return message;
});
}
}
// 消费者:库存服务
@Service
@RabbitListener(queues = "stock-queue")
public class StockConsumer {
@RabbitHandler
public void handleOrderCreate(OrderDTO order, Channel channel, @Payload long deliveryTag) {
try {
// 幂等性检查
String key = "processed:" + order.getOrderNo();
if (redisTemplate.hasKey(key)) {
channel.basicAck(deliveryTag, false);
return;
}
stockService.deductStock(order.getProductId(), order.getQuantity());
redisTemplate.opsForValue().set(key, "1", 24, TimeUnit.HOURS);
channel.basicAck(deliveryTag, false);
} catch (Exception e) {
channel.basicNack(deliveryTag, false, true);
}
}
}
面试模拟
Q:RabbitMQ、Kafka、RocketMQ如何选型?
A:根据业务场景选择:1. 需要事务消息 → RocketMQ;2. 需要极高吞吐量 → Kafka;3. 路由规则复杂 → RabbitMQ;4. 综合考虑 → RocketMQ(阿里开源,功能最全)。
Q:如何保证消息不丢失?
A:三道防线:1. 生产者端:Confirm机制/同步发送+重试;2. Broker端:消息持久化;3. 消费者端:手动ACK,消费失败进入重试队列或死信队列。