bigywater.tech
Kafka 内部原理 · 51

Replica Fetcher:Follower 如何拉取 Leader 数据

往一个分区持续写入30万条消息制造压力,用kafka-log-dirs.sh查leader和两个follower磁盘上的真实字节数和offsetLag,看Replica Fetcher真实追数据的速度和相关配置。

0
持续写入压力下真实观测到的offsetLag
500ms
Fetch请求没有新数据时真实最长的挂起时间

验证:Follower不是被动等推送,是它自己主动去拉

命令 · shell $ kafka-configs.sh --bootstrap-server localhost:19092 --describe --entity-type brokers --entity-name 1 --all \ | grep -E "num.replica.fetchers|replica.fetch"
真实实测 · 本机执行输出
num.replica.fetchers=1
replica.fetch.min.bytes=1
replica.fetch.wait.max.ms=500
replica.lag.time.max.ms=30000

每个Follower broker真实为它复制的每一个Leader broker维护一个专门的ReplicaFetcherThread,这个线程真实按跟consumer完全一样的Fetch协议向Leader发请求——"给我从offset X开始的数据",如果暂时没有新数据,请求会真实挂起最多replica.fetch.wait.max.ms(500毫秒),一旦Leader真实写入了新数据就立刻返回,不需要真的等满500毫秒。replica.lag.time.max.ms(30秒)则真实是ISR的判定标准:Follower真实超过这么久没有成功拉到最新数据,就会被踢出ISR。

验证:往一个分区疯狂写入,三个副本磁盘上的字节数真实同步得看不出差距

命令 · python for i in range(300000): p.produce("order-demo", partition=1, value=(b"x"*200)) # 真实故意不等flush,制造持续写入压力
真实实测 · 本机执行输出(用kafka-log-dirs.sh在写入过程中查询)
broker 1(follower)  order-demo-1  size=18120599  offsetLag=0
broker 2(leader)    order-demo-1  size=18120599  offsetLag=0
broker 3(follower)  order-demo-1  size=18120599  offsetLag=0
这份查询是在客户端本地发送队列已经写满(librdkafka默认queue.buffering.max.messages=100000,真实抛出过Queue full)、还有数据正在飞往Leader的时候真实做的,结果三个副本磁盘上的字节数真实一模一样,offsetLag真实全部是0。这不代表Follower复制"零延迟",而是本机loopback网络加上真实很小的写入包体,复制速度快到用kafka-log-dirs.sh这种秒级查询工具根本捕捉不到真实的滞后窗口——真实的滞后会发生在Follower磁盘写入变慢、跨机房网络延迟增加、或者Leader突然涌入远超Follower拉取速度的流量这几种场景下,本机这次实验条件下都不满足,所以看到的是一个诚实的"没有可观测滞后",而不是复制机制不存在滞后这件事本身。

分步演示:Follower真实追数据追得有多快

每一步都是本文上面用kafka-log-dirs.sh跑出来的原始结果。

持续写入压力下,三个副本的磁盘字节数真实同步
这一步新验证的状态

    参考与说明

    • 数据来自本机3节点Kafka 4.3.1集群,order-demo分区1(leader=broker2),客户端redis-py持续写入30万条200字节消息。
    • 没有验证:跨机房真实网络延迟下Follower滞后的真实表现;replica.lag.time.max.ms真实触发ISR踢出的场景(本机没能真实制造出持续30秒的滞后)。
    京ICP备2026067502号-1京公网安备11010502063487号