什么是 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 管理控制台,方便监控管理
🔧 插件丰富丰富的插件系统,功能可扩展

主流消息队列对比

特性RabbitMQKafkaRocketMQActiveMQ
语言ErlangScala/JavaJavaJava
协议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);
    }
}

📝 本章小结

通过本章学习,你应该已经了解:

  1. 消息队列是什么 - 应用程序之间异步通信的方式
  2. 为什么需要消息队列 - 异步处理、应用解耦、流量削峰
  3. RabbitMQ 的优势 - 可靠、灵活、功能丰富
  4. 常见应用场景 - 订单处理、秒杀系统、日志收集、延时任务

下一步

了解了 RabbitMQ 的基本概念后,让我们动手 安装 RabbitMQ 吧!