文章目录
- 前言
-
- [1. 为什么在秒杀场景中用 Kafka 消息队列异步下单?](#1. 为什么在秒杀场景中用 Kafka 消息队列异步下单?)
- [2. Kafka 消息队列的基础概念回顾](#2. Kafka 消息队列的基础概念回顾)
- [3. 秒杀中 Kafka 常见高频问题解析](#3. 秒杀中 Kafka 常见高频问题解析)
-
- [Q1. 如何保证 Kafka 消息不丢失?](#Q1. 如何保证 Kafka 消息不丢失?)
- [Q2. 如何保证秒杀下单的**幂等性**?](#Q2. 如何保证秒杀下单的幂等性?)
- [Q3. Kafka 如何保证**顺序消费**?](#Q3. Kafka 如何保证顺序消费?)
- [Q4. 如果 Kafka 消费者宕机,消息会丢吗?](#Q4. 如果 Kafka 消费者宕机,消息会丢吗?)
- [Q5. `fromBeginning: true/false` 有什么区别?](#Q5.
fromBeginning: true/false
有什么区别?) - [Q6. 如何处理消费积压(Lag)?](#Q6. 如何处理消费积压(Lag)?)
- [Q7. Kafka 与 RabbitMQ、RocketMQ 区别?](#Q7. Kafka 与 RabbitMQ、RocketMQ 区别?)
- [Q8. 秒杀如何防止**超卖**和**重复下单**?](#Q8. 秒杀如何防止超卖和重复下单?)
- [4. 还可以进一步问:](#4. 还可以进一步问:)
- [5. 实战代码相关点](#5. 实战代码相关点)
- [📦 小结](#📦 小结)
前言
⚡NestJS + Kafka 秒杀系统完整实践总结
1. 为什么在秒杀场景中用 Kafka 消息队列异步下单?
目的 | 解释 |
---|---|
削峰填谷 | 防止高峰期数据库写入爆炸,流量先进入 Kafka 排队缓冲 |
异步处理 | 秒杀请求响应快,前端体验好,不必等待订单完成 |
系统解耦 | 秒杀接口只负责扣库存,不负责下单/支付,微服务更灵活 |
高可用 | Kafka 支持分区冗余、副本机制,保证即使节点挂了数据也不丢失 |
2. Kafka 消息队列的基础概念回顾
- Producer:生产者,发送消息到 Topic
- Consumer:消费者,从 Topic 拉取消息
- Topic:消息分类
- Partition:Topic 的物理分片(提高并发)
- Consumer Group:一组消费者分担 Topic 消费负载
- Offset :每条消息在 Partition 中的位移标记(消费进度)
3. 秒杀中 Kafka 常见高频问题解析
Q1. 如何保证 Kafka 消息不丢失?
✅ 生产者配置:
acks=all
- 开启
retries
重试
✅ 消费者端:
- 手动提交 offset,确保消息成功消费后提交(防止未消费即确认)
✅ Broker端:
- 多副本(replication.factor >= 3)
- 控制器选举稳定(controller.quorum.voters)
Q2. 如何保证秒杀下单的幂等性?
- 订单表中
orderId
为唯一键,消费 Kafka 消息时先查询是否已存在 - 使用 Redis 快速幂等检查(如 setnx
seckill:order:{orderId}
) - Kafka 消费端设计幂等消费逻辑(消费失败时可重试)
Q3. Kafka 如何保证顺序消费?
- Kafka 本身 分区内有序 ,但跨分区无序
- 秒杀时可以将同一商品
skuId
哈希到同一分区 - 保证同一商品的秒杀请求在同一分区内消费,从而局部有序
Q4. 如果 Kafka 消费者宕机,消息会丢吗?
不会丢。
- Kafka 通过 offset 机制保存消费进度
- consumer 重新启动后会从上次提交的 offset 继续拉取消费
- 注意开启合适的 retention(消息保留期)
Q5. fromBeginning: true/false
有什么区别?
参数 | 含义 |
---|---|
true |
从最早的消息开始消费(包括旧消息) |
false |
只消费新产生的消息(默认) |
通常在秒杀系统消费订单消息时用 false
。
Q6. 如何处理消费积压(Lag)?
- 增加消费者实例数,提高消费并发
- 优化业务逻辑,降低单次消费时间
- 监控
lag
,及时告警
Q7. Kafka 与 RabbitMQ、RocketMQ 区别?
项目 | Kafka | RabbitMQ | RocketMQ |
---|---|---|---|
优势 | 高吞吐、大数据场景、分区机制 | 灵活、易用、适合小系统 | 延时消息、事务消息、轻量 |
应用场景 | 秒杀、日志、流式处理 | 普通业务异步化 | 金融领域、分布式事务 |
顺序保证 | 分区内有序 | 可设置顺序消费(但吞吐低) | 支持严格顺序 |
秒杀更推荐 Kafka(吞吐量高)。
Q8. 秒杀如何防止超卖 和重复下单?
-
超卖问题:
- Redis 预扣库存(Lua 原子脚本扣减)
- 数据库底层库存扣减二次校验(最终一致性)
-
重复下单问题:
- Redis
setnx
防重复 - 订单表
orderId
唯一约束 + Kafka 幂等消费处理
- Redis
4. 还可以进一步问:
- 如何配置和管理 Kafka 的 groupId/topic?
- ➔
.env
配置 +registerAsync
动态注入
- ➔
- 如何监控 Kafka 消费端健康状态?
- ➔ 用 Prometheus 采集 lag、consumer status
- 如何处理消费失败?
- ➔ try-catch+死信队列(DLQ)+补偿机制
- 如何保证消息处理高可用?
- ➔ 多实例部署、分区均衡、自动负载迁移
5. 实战代码相关点
- 消费者模块用
@Injectable()
注册 Nest 服务,onModuleInit() 启动消费 - KafkaProducerService 独立封装 Producer
- 消费端手动 commit offset,控制消费确认
- Topic、GroupId 支持动态环境配置(.env)
📦 小结
✅ 秒杀系统本质是"高速扣库存 + 异步下单 + 幂等保护",Kafka 消息队列正好完美契合这套需求。