当前位置: 首页 > news >正文

消息队列中的推模式与拉模式

消息队列的推(Push)模式拉(Pull)模式是两种核心的消息投递方式。现在有个疑问:

  • 推模式下,消费者只需要从自己的内存缓存区取消息,响应速度不是更快吗?
  • 那为什么 Kafka、RocketMQ 这些高性能 MQ 都采用拉模式,而 RabbitMQ 却用推模式呢?

一、定义

  • 推模式(Push)
    Broker 主动把消息推送给消费者,消费者只需要处理并返回 ACK。

  • 拉模式(Pull)
    消费者主动从 Broker 拉取消息,决定什么时候拉、一次拉多少。


二、推模式的优缺点

优点

  1. 低延迟:消息一到,Broker 立即推送,消费者第一时间收到。
  2. 客户端逻辑简单:消费者只要处理消息,不需要主动拉取逻辑。

缺点

  1. 浪费性能:一条一条的推送,网络效率低,磁盘IO 频繁。
  2. 流控难:Broker 不知道消费者的处理能力,如果大量消息发过来,可能把消费者“压垮”。
  3. OOM 风险:消费者处理慢时,大量消息在消费者的缓冲区存着,本地内存缓存区可能爆掉。
  4. Broker 堆积:如果消费者消息在本地堆积,迟迟不 ACK,MQ也不能删掉消息,所以消息也会卡在 Broker。

👉 不过对于OOM,RabbitMQ 的解决方案是:

  • basic.qos(prefetch=N) 控制 Broker 最多同时推 N 条未 ACK 的消息,之后不让推了。

三、拉模式的优缺点

优点

  1. 天然流控:消费者有多大能力就拉多少,不会被淹死。
  2. 支持批量拉取:一次拉一批,提升磁盘 IO 和网络效率。
  3. 模型简单:消费者只需记住自己的 offset,从 Broker 顺序拉取。

缺点

  1. 看似延迟更高:需要主动拉,拉不到就白费性能。

👉 但 Kafka、RocketMQ 有解决方案,采用了 长轮询(Long Polling) 技术:

  • 没消息时,服务端挂起请求,不占 CPU;
  • 一旦有新消息,立即被唤醒,立刻返回;
  • 延迟几乎和推模式一样。
  • 如果长轮询的多了,用 IO多路复用,挂起大量 socket,内核帮你监控 socket 是否有事件(比如新消息写入)。

四、为什么 Kafka / RocketMQ 用拉模式?

  1. 流控更自然:消费者自己决定速率,避免被 Broker 压垮。
  2. 批量高吞吐:一次拉一批,磁盘顺序读 + 网络批量传输,效率极高。
  3. 存储模型适配:Kafka、RocketMQ 的消息是顺序日志(append-only log),消费者只需根据 offset 拉取。
  4. 多消费者组支持:不同组各自维护 offset,拉模式更简单。
  5. 延迟不输推模式:长轮询让拉模式几乎和推一样实时。

五、为什么 RabbitMQ 用推模式?

  1. AMQP 协议语义:RabbitMQ 遵循 AMQP,规定 Broker 负责“投递消息”。
  2. 定位不同:RabbitMQ 更偏向中小规模消息传递、低延迟场景(如金融、微服务通信)。
  3. 路由复杂性:RabbitMQ 的 Exchange、Binding、Routing Key 等路由规则,交由 Broker 统一处理后推送,比让消费者自己拉更合理。

六、对比总结

特性推模式(RabbitMQ)拉模式(Kafka/RocketMQ)
定位低延迟、复杂路由、中小规模通信高吞吐、日志流、大数据场景
延迟极低长轮询优化后 ≈ 推模式
流控需要额外机制(prefetch)天然支持,消费者自控
吞吐量单条为主,批量弱批量拉取,高吞吐
存储模型队列(需要 ACK 管理状态)顺序日志(消费者自己管理 offset)

七、结论

  • RabbitMQ 用推模式:因为它定位在 低延迟、强路由能力 的消息分发,消息量可控,推模式能更快送达。
  • Kafka/RocketMQ 用拉模式:因为它们面向 海量日志流和大数据处理,需要批量、高吞吐和强流控,拉模式天然适配。
http://www.dtcms.com/a/337218.html

相关文章:

  • C++/Java双平台表单校验实战:合法性+长度+防重复+Tab顺序四重守卫
  • 【从0开始学习Java | 第14篇】集合(上)
  • Day8--滑动窗口与双指针--1004. 最大连续1的个数 III,1658. 将 x 减到 0 的最小操作数,3641. 最长半重复子数组
  • 考问通系统测试分析报告
  • Golang 语言中的指针操作
  • Android中使用RxJava实现网络请求与缓存策略
  • 实习两个月总结
  • 通义万相Wan2.1- 阿里推出的开源视频生成大模型
  • 从哲学(业务)视角看待数据挖掘:从认知到实践的螺旋上升
  • Elasticsearch查询中的track_total_hits参数
  • 【网络安全实验报告】实验五:网络嗅探及安全性分析
  • 在阿里云 CentOS Stream 9 64位 UEFI 版上离线安装 Docker Compose
  • CentOS 7更换国内镜像源
  • CentOS 7安装OpenVASGVM指南
  • 国产!全志T113-i 双核Cortex-A7@1.2GHz 工业开发板—ARM + DSP、RISC-V核间通信开发案例
  • [数据结构] ArrayList 与 顺序表
  • OVS:ovn为什么默认选择Geneve作为二层隧道网络协议?
  • 【Day 30】Linux-Mysql数据库
  • 大数据计算引擎(三)——Elasticsearch入门
  • uart串口 day57
  • 产品经理如何提升职场学习能力?破除成长瓶颈
  • Vue+Flask 电影协同推荐可视化平台 前后端分离 大数据分析
  • Windows从零到一安装KingbaseES数据库及使用ksql工具连接全指南
  • 05.用户和组管理命令
  • 【机器学习】FPR(False Positive Rate,误报率)是什么?
  • Zephyr下ESP32S3开发环境搭建(Linux篇)
  • 深度研究系统、方法与应用的综述
  • Transformer架构的编码器和解码器介绍
  • 管理本地用户和组:红帽企业 Linux 系统安全的基础
  • TDengine `count_window` 指定列计数功能用户手册