因为…所以… — 从同步阻塞到消息驱动完整因果推导
发送方发完消息 → MQ还没持久化就宕机 → 消息丢失!
消费方取了消息 → 处理到一半挂了 → 消息丢失!
1. 生产端:发送到MQ时网络抖动 → 消息没到MQ
2. MQ端:MQ收到但没持久化就宕机 → 消息在内存中丢失
3. 消费端:消费者取了消息但处理失败 → 消息没了
消费端处理成功了,但ACK时网络断了 → MQ以为没消费 → 重新投递 → 同一条消息被消费两次!
3条消息进入3个队列,消费者并发消费 → 可能先消费"发货"再消费"创建" → 逻辑错误
一直重试?其他消息都堵在后面了。直接丢弃?那是业务数据,丢了就出大事。
| 面试题 | 因为…所以… |
|---|---|
| 为什么用MQ | 因为同步调用阻塞+耦合 → 所以MQ异步解耦+削峰 |
| 如何保证不丢消息 | 因为3个环节都可能丢 → 生产端确认+MQ持久化+消费端手动ACK |
| 如何保证幂等 | 因为网络抖动导致重复消费 → 所以唯一ID去重表/状态机/乐观锁 |
| 顺序消费 | 因为同一业务的消息乱序会出错 → 所以sharding key路由到同一队列 |
| 死信队列 | 因为重试3次还是失败 → 所以进入死信队列等待人工/自动补偿 |
| 延迟队列 | 因为业务需要"30分钟后执行" → 所以TTL+死信/RocketMQ延迟级别 |
| MQ选型 | 因为需求不同 → Kafka(吞吐)/RabbitMQ(可靠)/RocketMQ(全功能) |
| 消息积压 | 因为消费速度<生产速度 → 所以扩容消费者+跳过非核心+监控告警 |