什么是 RabbitMQ
📖 消息队列简介
什么是消息队列?
消息队列(Message Queue,简称 MQ) 是一种应用程序之间的通信方式。想象一下现实生活中的快递柜:
- 📦 发件人(生产者)把包裹放入快递柜
- 📮 快递柜(消息队列)暂时保管包裹
- 👤 收件人(消费者)在方便的时候取走包裹
这种模式让发件人和收件人不需要同时在场,实现了异步通信。
┌──────────┐ 消息 ┌──────────────┐ 消息 ┌──────────┐
│ 生产者 │ ────────> │ 消息队列 │ ────────> │ 消费者 │
│ Producer │ │ Message Queue │ │ Consumer │
└──────────┘ └──────────────┘ └──────────┘
为什么需要消息队列?
在传统的同步调用中:
// 同步调用示例 - 用户下单
public void createOrder(Order order) {
// 1. 创建订单 - 50ms
orderService.create(order);
// 2. 扣减库存 - 50ms
inventoryService.decrease(order);
// 3. 发送短信通知 - 100ms
smsService.send(order.getUserPhone(), "下单成功");
// 4. 发送邮件通知 - 100ms
emailService.send(order.getUserEmail(), "下单成功");
// 5. 增加积分 - 50ms
pointService.add(order.getUserId(), order.getPoints());
// 总耗时: 350ms,用户需要等待很久!
}
使用消息队列后:
// 异步调用示例 - 用户下单
public void createOrder(Order order) {
// 1. 创建订单 - 50ms(核心业务,同步执行)
orderService.create(order);
// 2. 发送消息到队列 - 5ms(非核心业务,异步处理)
rabbitTemplate.convertAndSend("order.created", order);
// 总耗时: 55ms,用户体验大幅提升!
}
// 其他服务异步消费消息,各自处理自己的业务
消息队列的三大作用
1️⃣ 异步处理(提升性能)
同步模式(串行):
用户请求 → 下单(50ms) → 扣库存(50ms) → 发短信(100ms) → 响应用户
总耗时: 200ms
异步模式(并行):
用户请求 → 下单(50ms) → 发送MQ(5ms) → 响应用户
总耗时: 55ms
↓
MQ异步处理: 扣库存 + 发短信(后台并行执行)
2️⃣ 应用解耦(降低依赖)
紧耦合(直接调用):
┌────────┐ ┌────────┐
│ 订单服务 │────→│ 库存服务 │ 库存服务挂了,订单服务也会失败!
└────────┘ └────────┘
松耦合(通过MQ):
┌────────┐ ┌────┐ ┌────────┐
│ 订单服务 │────→│ MQ │────→│ 库存服务 │ 库存服务挂了,消息暂存MQ,
└────────┘ └────┘ └────────┘ 恢复后继续消费,订单服务不受影响!
3️⃣ 流量削峰(保护系统)
无MQ(直接扛压):
秒杀请求 10万/秒
↓
┌─────────────────────────┐
│ 数据库(最大1万/秒) │ ← 数据库直接被打崩!
└─────────────────────────┘
有MQ(削峰填谷):
秒杀请求 10万/秒
↓
┌─────────────────────────┐
│ 消息队列(缓冲区) │ ← 请求先存入队列
└─────────────────────────┘
↓ 1万/秒(匀速消费)
┌─────────────────────────┐
│ 数据库(最大1万/秒) │ ← 数据库稳定运行
└─────────────────────────┘
🐰 RabbitMQ 介绍
什么是 RabbitMQ?
RabbitMQ 是一个开源的消息代理软件(也称为消息中间件),它实现了 AMQP(高级消息队列协议) 标准。
RabbitMQ 的 Logo 是一只兔子 🐰,寓意消息传递像兔子一样快速!
为什么选择 RabbitMQ?
| 特性 | 说明 |
|---|---|
| 🔒 可靠性 | 支持持久化、消息确认、发布确认等机制 |
| 🔄 灵活路由 | 通过交换机实现多种消息路由策略 |
| 🌐 集群支持 | 支持多节点集群,实现高可用 |
| 🔌 多协议 | 支持 AMQP、MQTT、STOMP 等多种协议 |
| 💻 多语言 | 支持 Java、Python、Go、.NET 等多种语言 |
| 🖥️ 管理界面 | 自带 Web 管理控制台,方便监控管理 |
| 🔧 插件丰富 | 丰富的插件系统,功能可扩展 |
主流消息队列对比
| 特性 | RabbitMQ | Kafka | RocketMQ | ActiveMQ |
|---|---|---|---|---|
| 语言 | Erlang | Scala/Java | Java | Java |
| 协议 | AMQP | 自定义 | 自定义 | JMS |
| 吞吐量 | 万级 | 百万级 | 十万级 | 万级 |
| 延迟 | 微秒级 | 毫秒级 | 毫秒级 | 毫秒级 |
| 可靠性 | 高 | 高 | 非常高 | 高 |
| 适用场景 | 企业应用 | 大数据/日志 | 金融/电商 | 传统企业 |
选型建议
- 中小型项目:推荐 RabbitMQ,功能完善、易于使用
- 大数据场景:推荐 Kafka,吞吐量高
- 金融电商:推荐 RocketMQ,阿里开源,功能强大
🎯 RabbitMQ 应用场景
场景一:订单系统
// 用户下单后,发送消息通知其他服务
@Service
public class OrderService {
@Autowired
private RabbitTemplate rabbitTemplate;
public void createOrder(Order order) {
// 1. 保存订单到数据库
orderRepository.save(order);
// 2. 发送订单创建消息(异步通知其他服务)
rabbitTemplate.convertAndSend("order.exchange", "order.created", order);
// 库存服务、积分服务、通知服务等会各自消费这条消息
}
}
场景二:秒杀系统
// 秒杀请求先入队列,再匀速处理
@Service
public class SeckillService {
@Autowired
private RabbitTemplate rabbitTemplate;
public String seckill(Long userId, Long productId) {
// 构建秒杀请求
SeckillRequest request = new SeckillRequest(userId, productId);
// 发送到消息队列(毫秒级响应)
rabbitTemplate.convertAndSend("seckill.queue", request);
return "秒杀请求已提交,请稍后查看结果";
}
}
// 消费者匀速处理秒杀请求
@Component
public class SeckillConsumer {
@RabbitListener(queues = "seckill.queue")
public void handleSeckill(SeckillRequest request) {
// 匀速处理每个秒杀请求
seckillService.doSeckill(request);
}
}
场景三:日志收集
// 将日志发送到消息队列,统一收集处理
@Aspect
@Component
public class LogAspect {
@Autowired
private RabbitTemplate rabbitTemplate;
@AfterReturning("execution(* com.example.controller.*.*(..))")
public void logAfterReturning(JoinPoint joinPoint) {
LogMessage log = new LogMessage();
log.setMethod(joinPoint.getSignature().getName());
log.setTimestamp(LocalDateTime.now());
// 异步发送日志到队列
rabbitTemplate.convertAndSend("log.queue", log);
}
}
场景四:延时任务
// 订单超时未支付自动取消
@Service
public class OrderService {
@Autowired
private RabbitTemplate rabbitTemplate;
public void createOrder(Order order) {
orderRepository.save(order);
// 发送延时消息,30分钟后检查支付状态
rabbitTemplate.convertAndSend(
"order.delay.exchange",
"order.delay",
order.getId(),
message -> {
// 设置延时30分钟
message.getMessageProperties().setDelay(30 * 60 * 1000);
return message;
}
);
}
}
// 30分钟后自动消费,检查订单状态
@RabbitListener(queues = "order.delay.queue")
public void checkOrderPayment(Long orderId) {
Order order = orderRepository.findById(orderId);
if (order.getStatus() == OrderStatus.UNPAID) {
// 取消未支付订单
orderService.cancel(orderId);
}
}
📝 本章小结
通过本章学习,你应该已经了解:
- 消息队列是什么 - 应用程序之间异步通信的方式
- 为什么需要消息队列 - 异步处理、应用解耦、流量削峰
- RabbitMQ 的优势 - 可靠、灵活、功能丰富
- 常见应用场景 - 订单处理、秒杀系统、日志收集、延时任务
下一步
了解了 RabbitMQ 的基本概念后,让我们动手 安装 RabbitMQ 吧!
