跳到主要内容

消息队列

问题

消息队列在后端架构中起什么作用?常见的消息队列有哪些?前端需要了解吗?

答案

消息队列的作用

作用说明示例
异步解耦生产者不需要等消费者处理完下单后异步发短信通知
削峰填谷流量高峰时积压在队列中,慢慢消费秒杀场景
可靠投递消息持久化,不怕服务重启丢失支付回调
广播一条消息多个消费者处理订单创建后,库存、物流、通知各自处理

常见消息队列对比

维度RabbitMQKafkaRedis Pub/SubBullMQ
定位通用消息代理高吞吐流处理轻量发布订阅Node.js 任务队列
吞吐量万级/s百万级/s万级/s万级/s
持久化✅(Redis)
消息确认
适用企业应用大数据/日志简单广播Node.js 后台任务

BullMQ 实战(Node.js 最常用)

queue-setup.ts
import { Queue, Worker } from 'bullmq';
import IORedis from 'ioredis';

const connection = new IORedis({ host: 'localhost', port: 6379 });

// 创建队列
const emailQueue = new Queue('email', { connection });

// 生产者:添加任务
await emailQueue.add('send-welcome', {
to: 'user@example.com',
subject: '欢迎注册',
template: 'welcome',
});

// 消费者:处理任务
const worker = new Worker('email', async (job) => {
console.log(`Processing job ${job.id}: ${job.name}`);
await sendEmail(job.data);
}, { connection, concurrency: 5 });

worker.on('completed', (job) => {
console.log(`Job ${job.id} completed`);
});

worker.on('failed', (job, err) => {
console.error(`Job ${job?.id} failed:`, err.message);
});

前端相关的消息队列场景

frontend-scenarios.ts
const frontendRelatedScenarios = {
// 1. 消息推送:后端通过队列处理后,推送到前端 WebSocket
realtimeNotification: '订单状态变更 → 队列 → WebSocket → 前端更新',

// 2. 文件处理:前端上传文件后,后端异步处理
fileProcessing: '上传图片 → 队列 → 压缩/裁剪 → 通知前端完成',

// 3. SSE 推送:AI 聊天场景,消息通过队列串联
aiChat: '用户提问 → 队列 → AI 处理 → SSE 流式推送到前端',

// 4. 导出任务:前端触发、后端异步生成
exportTask: '点击导出 → 队列 → 生成 Excel → 通知前端下载',
};

常见面试问题

Q1: 消息丢失怎么办?

答案

三个环节保证不丢消息:

  1. 生产者确认:发送后等待队列 ACK
  2. 队列持久化:消息写入磁盘
  3. 消费者确认:处理完后手动 ACK,失败自动重试

Q2: 消息重复消费怎么办?

答案

消费者实现幂等性

  • 用消息 ID 做去重(数据库唯一索引、Redis SetNX)
  • 业务层幂等(如支付接口根据订单号幂等)

Q3: 死信队列是什么?

答案

消费失败多次后,消息会进入死信队列(Dead Letter Queue),便于人工排查和重新处理,不阻塞正常队列。

Q4: Kafka 和 RabbitMQ 怎么选?

答案

  • RabbitMQ:对消息可靠性要求高、需要复杂路由、消息量不大
  • Kafka:超高吞吐量、日志/事件流处理、需要消息回溯

Q5: 前端工程师需要了解消息队列吗?

答案

需要了解基本概念,原因:

  1. BFF 层可能需要与队列交互
  2. 理解后端架构有助于排查问题
  3. Node.js 后端常用 BullMQ 处理异步任务
  4. 实时功能的实现链路通常涉及消息队列

相关链接