RocketMQ 与 Kafka 长轮询详解

RocketMQ 与 Kafka 长轮询详解

一、背景

Consumer 消费消息有两种基本模式:

模式 说明 问题
Push Broker 主动推送消息给 Consumer Consumer 可能来不及处理,造成积压
Pull Consumer 主动向 Broker 拉取消息 频繁拉取浪费资源;消息到达慢导致延迟

长轮询 是对 Pull 模式的优化:Consumer 发起请求后,若暂无消息,Broker 不立即返回,而是挂起请求,等到有新消息或超时后再响应。既避免了频繁空轮询,又保证了消息的实时性。


二、RocketMQ 长轮询

2.1 整体机制

RocketMQ 本质是 Pull 模式,通过长轮询模拟 Push 的实时感。

复制代码
Consumer                     Broker
   │                            │
   │  Pull 请求(带超时时间)    │
   │ ─────────────────────────> │
   │                            │ 有消息?
   │                            ├── YES → 立即返回消息
   │                            │
   │                            └── NO  → 挂起请求
   │                                      进入 PullRequestHoldService
   │                                      等待新消息到达 or 超时
   │                                          │
   │                                  新消息写入 CommitLog
   │                                          │
   │ <─────────────────────────  唤醒挂起请求,立即返回消息
   │                            │
   │  立即发起下一次 Pull        │
   │ ─────────────────────────> │

2.2 核心组件

复制代码
PullMessageProcessor          # 处理 Pull 请求的入口
  ↓(无消息时)
PullRequestHoldService        # 管理挂起请求的后台线程
  ├── 每 5 秒定时轮询(短轮询兜底,防止消息遗漏)
  └── 被 ReputMessageService 实时唤醒

ReputMessageService           # 监听 CommitLog 写入
  └── 新消息写入后调用 notifyMessageArriving()
        └── 唤醒对应 Topic/Queue 的挂起请求

2.3 挂起超时时间

配置 挂起时长 说明
longPollingEnable=true(默认) 30 秒 长轮询,实时性强
longPollingEnable=false 1 秒 短轮询,兜底方案

2.4 唤醒时机

  1. 实时唤醒 :新消息写入 CommitLog → ReputMessageServicenotifyMessageArriving() → 立即唤醒
  2. 超时唤醒PullRequestHoldService 定时线程每 5 秒扫描一次,超过挂起时长则强制返回

2.5 关键特点

  • 消息级别触发:一条新消息写入即可唤醒,延迟极低(毫秒级)
  • 设计目标:低延迟,尽快将消息送达 Consumer
  • 适合场景:对消息实时性要求高的业务(如订单、支付通知)

三、Kafka 长轮询

3.1 整体机制

Kafka Consumer 调用 poll(timeout) 发起 Fetch 请求,Broker 端通过 DelayedFetch 实现挂起等待。

复制代码
Consumer                     Kafka Broker
   │                            │
   │  Fetch 请求                │
   │  fetch.min.bytes=1MB       │
   │  fetch.max.wait.ms=500ms   │
   │ ─────────────────────────> │
   │                            │ 数据量 >= fetch.min.bytes?
   │                            ├── YES → 立即返回
   │                            │
   │                            └── NO  → 创建 DelayedFetch
   │                                      放入 DelayedOperationPurgatory
   │                                      等待触发条件:
   │                                      ① 数据量 >= fetch.min.bytes
   │                                      ② 等待时间 >= fetch.max.wait.ms
   │                                      满足其一则返回
   │ <─────────────────────────  返回数据(可能是空或少量消息)

3.2 核心组件

复制代码
KafkaApis                         # 处理 Fetch 请求入口
  ↓(数据不足时)
DelayedFetch                      # 延迟 Fetch 操作对象
  └── 放入 DelayedOperationPurgatory(炼狱)
          ├── 新消息写入 Partition → tryComplete() → 检查是否满足条件
          └── fetch.max.wait.ms 超时 → onExpiration() → 强制返回

DelayedOperationPurgatory(炼狱) 是 Kafka 管理所有延迟操作的核心组件,长轮询、延迟生产(acks=-1)等都由它统一管理。

3.3 核心配置参数

Consumer 端:

properties 复制代码
# 每次 Fetch 最少返回的数据量(默认 1 字节,即有消息就返回)
fetch.min.bytes=1

# Broker 最长等待时间(默认 500ms)
fetch.max.wait.ms=500

# 每次 poll 最多拉取的消息条数
max.poll.records=500

# Consumer 两次 poll 的最长间隔(超过则认为 Consumer 宕机)
max.poll.interval.ms=300000

Broker 端(副本同步):

properties 复制代码
# 副本 Fetch 最小字节数
replica.fetch.min.bytes=1

# 副本 Fetch 最长等待时间
replica.fetch.wait.max.ms=500

3.4 批量优化场景

通过调大 fetch.min.bytes,可以实现攒批效果:

properties 复制代码
# 至少积累 1MB 数据再返回,减少网络交互次数,提升吞吐量
fetch.min.bytes=1048576
fetch.max.wait.ms=1000

3.5 关键特点

  • 数据量阈值控制 :通过 fetch.min.bytes 攒批,减少网络交互
  • 设计目标:高吞吐,批量拉取摊薄网络开销
  • 适合场景:日志采集、大数据流处理等吞吐量优先的业务

四、两者对比

维度 RocketMQ Kafka
消费模型 Pull 模拟 Push 纯 Pull
挂起组件 PullRequestHoldService DelayedOperationPurgatory
唤醒粒度 消息级别(一条消息即唤醒) 数据量阈值(fetch.min.bytes
默认等待超时 30 秒 500ms
最小数据量控制 fetch.min.bytes(可配置)
实时性 极高(毫秒级) fetch.max.wait.ms 影响
吞吐量 中等 高(批量设计)
设计目标 低延迟 高吞吐
适用场景 订单、支付、实时通知 日志、埋点、大数据流

五、关键区别深度分析

5.1 触发粒度不同

复制代码
RocketMQ:消息级别触发
  一条消息写入 CommitLog → 立即唤醒挂起的 Consumer
  优势:延迟极低
  劣势:高消息频率下,唤醒过于频繁

Kafka:数据量阈值触发
  积累 fetch.min.bytes 数据 → 才返回给 Consumer
  优势:批量传输,网络效率高
  劣势:低流量时可能等到 fetch.max.wait.ms 超时才返回

5.2 设计目标不同

复制代码
RocketMQ 长轮询 → 追求低延迟
  消息产生 → 毫秒内送达 Consumer

Kafka 长轮询 → 追求高吞吐
  通过 fetch.min.bytes 攒批 → 单次网络传输携带更多数据

5.3 超时策略不同

复制代码
RocketMQ:30s 长超时
  维持长连接,减少重连开销
  超时后 Consumer 立即重新发起 Pull

Kafka:500ms 短超时(默认)
  快速返回空结果,由 Consumer poll() 循环控制节奏
  可调大以减少空轮询次数

六、总结

RocketMQ Kafka
一句话概括 用长轮询模拟 Push,追求实时 用长轮询攒批拉取,追求吞吐
核心参数 longPollingEnable、挂起 30s fetch.min.bytesfetch.max.wait.ms
选型建议 业务消息、实时性优先 数据流、吞吐量优先
相关推荐
小饼干在学嘎瓦2 分钟前
秒杀场景Redis做预扣减,问题在哪里?
数据库·redis·mybatis
码不停蹄的玄黓4 分钟前
生产可用的 Redis 分布式锁完整实现
数据库·redis·分布式
咸鱼翻身小阿橙7 分钟前
文件读写 + Qt Model/View + 自定义分页+搜索过滤
java·数据库·qt
l1t10 分钟前
DeepSeek总结的DuckDB-Iceberg 在 v1.5.3 中的新特性
数据库·duckdb
Database_Cool_10 分钟前
数据仓库弹性扩缩容怎么实现?阿里云 AnalyticDB MySQL Serverless 弹性架构详解
数据库·人工智能·阿里云
abcy07121312 分钟前
django聚合函数
数据库·sqlite
念越13 分钟前
数据库系统概论第6版王珊版:第二章关系代数与第三章SQL期末重点整理
数据库·sql·性能优化
TDengine (老段)16 分钟前
TDengine 数据保留与 TTL — 多级存储、过期删除与分层迁移
大数据·数据库·物联网·时序数据库·tdengine·涛思数据
安当加密030120 分钟前
等保2.0三级数据库加密:2026检查清单 + TDE部署实战(附脚本)
数据库·网络安全·数据安全·tde·等保2.0·数据库加密·tde透明加密
解决问题no解决代码问题23 分钟前
TiDB 原理与节点宕机实战讲解
数据库·tidb