前面几篇杀的都是整个 Broker 进程(kill -9),ISR 收缩看起来像是"进程死了才会被踢出去"。这次换一种的杀法:用 kill -STOP 把 Follower 进程暂停(进程还活着,只是不再被调度),看它会不会、什么时候被移出 ISR——用来验证 ISR 资格到底是看"进程存不存在"还是看"有没有跟上 Leader 的 Fetch 节奏"。
命令 · shell $ kill -STOP 52470 # 暂停 broker2 进程(这个分区的 Follower),不是杀死 $ ps -p 52470 -o pid,stat,comm $ kafka-topics.sh --bootstrap-server 127.0.0.1:19192,127.0.0.1:19392 --describe --topic isr-eligibility-demo
PID STAT COMM 52470 TN /opt/homebrew/opt/openjdk/libexec/openjdk.jdk/Contents/Home/bin/java Topic: isr-eligibility-demo Partition: 0 Leader: 1 Replicas: 1,2,3 Isr: 1,3
STAT 列的 T 是的"已停止但仍存在"的进程状态——ps 能查到这个 PID,操作系统认为它是活的,只是不再消耗 CPU、不会响应任何请求。这期间持续往这个分区写数据,broker2 因为进程被暂停,完全没法向 Leader 发 Fetch 请求。查到的结果是 Replicas: 1,2,3 里仍然列着 2(说明 Kafka 依然认为它是这个分区"理论上应该有"的副本),但 Isr: 1,3 里已经没有 2 了——这组数据直接证明 ISR 资格看的不是"进程活不活着",而是"有没有按时跟上数据"。用 kill -9 得到的结论会让人误以为两者是一回事,这次用 kill -STOP 把它们拆开了。
命令 · shell $ kafka-configs.sh --bootstrap-server 127.0.0.1:19192,127.0.0.1:19292,127.0.0.1:19392 \ --broker 1 --describe --all | grep replica.lag.time.max.ms
replica.lag.time.max.ms=30000 sensitive=false synonyms={DEFAULT_CONFIG:replica.lag.time.max.ms=30000}
--- 两次独立测量(SIGSTOP 到 describe 查出 Isr 不含 2)---
第一次:t+66.75s 查到 Isr: 1,3
第二次:t+96.60s 查到 Isr: 1,3(这次轮询间隔更大,命中的检查点更晚)
--- 恢复:kill -CONT 后重新加入 ISR ---
t+6.96s 查到 Isr: 1,2,3配置里 replica.lag.time.max.ms=30000,但两次测量到的"从暂停到查出被移出 ISR"都明显超过 30 秒(66.75s 和 96.6s)。如实说明:这不是配置数字不准,而是两层延迟叠加——一是 Broker 判断"该不该收缩 ISR"本身是周期性检查的(不是 lag 一超过 30000ms 就立刻触发,要等下一次检查点),二是这次测量用的探测工具本身也需要建立到集群的连接、等待响应,测量粒度做不到亚秒级精确。第三次尝试给 kafka-topics.sh 配了 4 秒的 request.timeout.ms 想测更细的粒度,结果命令本身超时失败、没有返回可用数据——这个失败也如实记录:不是每次尝试都能拿到更精确的数字,缩短探测工具的超时反而让探测本身变得不可靠。可信的结论是"移出 ISR 发生在 30 秒下限之后、大致 100 秒以内",不是一个精确到毫秒的数字。恢复方向的 6.96 秒则测得干净:kill -CONT 之后 Follower 立刻能重新发 Fetch 请求,只要追上 Leader 的 Log End Offset 就能马上重新进 ISR,不需要等任何周期性判断——这是测量中一次描述调用就拿到了确定结果,没有前面的时间不确定性。
ISR 资格是一个关于"数据是否追上"的判断,不是"进程是否存活"的判断——这次用 kill -STOP 让进程"活着但不干活",复现了这个区别:ps 能看到进程、Replicas 列表里还有它,但 Isr 里已经没有它。移出 ISR 有的滞后(这次测到 66-97 秒,明显超过配置的 30 秒阈值,因为收缩检查本身是周期性的),而恢复相对干净、只花了 7 秒左右。这也解释了为什么 acks=all 配合 min.insync.replicas=2(这次 topic 的配置)在 Follower 只是"卡住"而非"真的挂了"的场景下依然能持续写入:只要 ISR 里还剩 2 个副本,min.insync.replicas 的门槛就还够。
每一步都是本文上两节kill -STOP/-CONT、查ps和ISR得到的原始结果。