日期:2026-07-11
标签:#面试 #八股 #后端 #系统设计 #场景题
一句话答案
推模式实时性好但容易压垮慢消费者;拉模式由消费者控制节奏、易做批处理和故障恢复,因此主流 MQ 常以长轮询实现“使用体验像推、底层机制是拉”。
对比
| 维度 | 推模式 | 拉模式 |
|---|---|---|
| 实时性 | 通常更好 | 普通轮询受间隔影响,长轮询可改善 |
| 流量控制 | Broker 需要感知消费者能力 | 消费者天然控制速率 |
| 慢消费者 | 易堆积连接和请求 | 可暂停拉取并逐步追赶 |
| 批处理 | 较难动态控制批次 | 易按条数或字节批量拉取 |
| Broker 状态 | 需要维护推送与重试状态 | 相对简单 |
| 空轮询 | 无 | 短轮询可能浪费资源 |
面试口语版
如果追求极低延迟且消费者数量和能力稳定,可以使用推;但通用 MQ 更适合拉,因为消费端最清楚自己的处理能力,可以自然做背压、批量和位点恢复。拉模式的空轮询问题可用长轮询解决:请求没消息时 Broker 暂挂,有消息或超时再返回。
面试官追问
- 长轮询如何实现?
- 拉模式下如何避免重复消费?
- Push Consumer 为什么底层仍可能是拉?
面试官追问参考答案
1. 长轮询如何实现?
消费者发起带等待时间的拉取请求;没有新消息时 Broker 不立即返回,而是登记请求并挂起。当目标分区有新消息、等待超时或连接关闭时唤醒请求。实现需限制挂起请求数量并处理取消,避免连接和内存耗尽。
2. 拉模式下如何避免重复消费?
拉取和业务处理之间无法天然构成分布式原子事务,通常采用至少一次:业务成功后提交 Offset,失败重试,消费者通过业务唯一键或幂等状态机去重。若先提交 Offset 再处理,宕机可能丢消息,所以一般不这样做。
3. Push Consumer 为什么底层仍可能是拉?
客户端 SDK 可以在后台长轮询 Broker,收到消息后再回调用户代码,从 API 体验看像推。这样既保留消费者主动控制批量、速率和 Offset 的优势,也获得接近推送的低延迟。