ISR 和 OSR 的动态判定由 Leader 副本实时执行,依据 replica.lag.time.max.ms(默认10秒)超时未拉取数据为主、replica.lag.max.messages(默认4000)为辅;满足任一条件即剔出 ISR 进入 OSR,恢复同步后自动重新加入。

ISR 和 OSR 的动态判定,本质上是 Kafka Leader 副本对 Follower 副本“是否跟得上”的实时判断,不是静态配置,而是由两个核心时间/数量阈值共同驱动的运行时行为。Java 客户端本身不参与 ISR 判定,但生产者配置(如 acks=all)和消费者行为会受其直接影响。
ISR 的判定依据:两个硬性条件必须同时满足
Leader 会持续监控每个 Follower 的同步状态,只要任一条件不满足,该 Follower 就被移出 ISR、进入 OSR:
-
滞后消息条数超限:Follower 的 LEO(日志末尾偏移量)与 Leader 的 LEO 差值 >
replica.lag.max.messages(默认 4000)。注意:Kafka 3.0+ 已弃用此参数,实际以时间为主;旧版本仍可能生效。 -
同步请求超时:Follower 超过
replica.lag.time.max.ms(默认 10 秒)未向 Leader 发起 fetch 请求。这是当前最权威、默认启用的判定标准。
OSR 的形成不是“失败”,而是“暂时掉队”
一个副本进入 OSR 并不意味着它损坏或不可用,只是当前无法满足同步要求。常见原因包括:
- 网络瞬断或高延迟,导致 fetch 请求超时
- Follower 所在 Broker 正在 GC 或负载过高,响应变慢
- 磁盘写入瓶颈,导致本地日志追不上 Leader 推送速度
- 新副本加入后尚未完成全量同步(bootstrap 阶段)
ISR 的伸缩是自动且双向的
Leader 不仅会剔除慢副本,也会主动接纳恢复正常的副本:
立即学习“Java免费学习笔记(深入)”;
- 当 OSR 中的副本重新建立连接,并在
replica.lag.time.max.ms内稳定发送 fetch 请求,且其 LEO 追上 Leader(或差距在可接受范围内),Leader 就会将其加回 ISR - 这个过程无需人工干预,也不依赖 ZooKeeper(Kafka 3.3+ 使用 KRaft),完全由 Leader 独立维护
- 可通过 Kafka Admin API 或
kafka-topics.sh --describe实时查看各分区的 ISR 列表
Java 应用需关注的实操要点
虽然判定逻辑在 Broker 端,但 Java 开发者必须理解其影响并合理配置:
- 设置
acks=all时,消息只有被 ISR 中所有副本写入才认为“已提交”,若 ISR 缩小到只剩 Leader,acks=all实际退化为acks=1 - 若发现 ISR 频繁波动,应检查 Broker 日志中是否有
Removed {broker} from ISR或Added {broker} to ISR记录 - 调优建议:在稳定性优先场景,可适当增大
replica.lag.time.max.ms(如设为 30000),避免因短暂抖动误剔除;但不能过大,否则影响故障切换及时性



















