Kafka read_committed 为什么读不到最新消息?LSO 和 HW 有什么区别?
面试怎么回答
HW 是复制提交边界,LSO 还受最早未完成事务限制。read_committed 只交付稳定范围内可见的数据,并过滤中止事务,所以日志末尾在增长也可能暂时读不到。排查会对比日志、HW、LSO 和消费位置,定位长事务或生产者异常。它只解决读隔离,端到端一致性仍需正确提交 Offset 和处理结果写入。
先把这段讲顺;面试官追问时,再展开下面的原理和细节。
详细讲解
监控显示分区还有新消息,普通消费者能读到,设置 read_committed 的消费者却停住了。网络没断,也没发生 Rebalance。这里的差别可能来自事务可见边界。
HW 反映复制提交边界,LSO 进一步受未完成事务约束;read_committed 只能读取稳定范围内的已提交事务数据与非事务数据,还会跳过已中止事务。
先统一位点表示,避免差一争论
讨论日志位点时,有些材料说最后一条可读消息的位置,有些接口使用下一条记录位置作为边界,两种写法容易相差一。本文用“可读范围的上界”解释机制,具体监控值需按接口口径理解。
HW 描述复制层面已提交的数据边界;一个事务的记录即使已经复制,也可能还没有提交或中止。事务隔离消费者因此不能只依据 HW 决定是否把所有这些记录交给应用。
LSO 会被最早未结束事务挡住
在 read_committed 模式下,Kafka 需要等待事务结果明确。分区中最早的未结束事务会限制稳定可读范围,后面即使有别的记录已经完成,也不能简单跳过这个边界向后正常交付。
这能解释一种现象:Producer 持续写入,日志末尾不断增长,某个事务消费者却暂时看不到后续消息。它可能是在等待事务稳定,而非单纯因为消费者处理能力不足。判断前要同时看生产事务和分区进度。

read_committed 不保证业务处理恰好一次
这个选项决定读取哪些事务记录:中止的事务数据被过滤,已提交事务数据在稳定范围内可读,非事务数据也能被读取,但同样受相应范围约束。
它不会替应用自动提交正确的消费位置,也不会让外部数据库写入天然幂等。要实现端到端一致性,还要考虑消费位点与结果写入是否在同一事务协议内,或者采用幂等、去重和补偿。读隔离只是链路中的一个条件。
一个典型场景:消费积压来自没结束的事务
比如生产者开启事务后等待一个慢接口,长时间没有提交。运维看到 Lag 增长先增加 Consumer,结果读进度仍没有变化。检查事务状态与分区稳定边界后,发现记录在等待这个事务结束。
原告警以日志末尾减消费位置衡量积压,没有区分已可见待处理数据与事务暂不可见数据。正确处理是定位生产者事务生命周期、超时和异常路径,保证失败时能够中止,而不是让更多消费者一起等待。
排查要把三种进度放在一起
记录分区日志末尾、复制提交边界和事务稳定边界,再对照消费者位置与已提交 Offset。监控工具的 Lag 定义可能不同,先确认它选了哪个上界,才能解释“明明没有可读消息但积压很大”。
不要为了消除告警直接把隔离级别改成 read_uncommitted,这会改变业务可见性并暴露可能中止的事务数据。可以在独立诊断环境比较两种读取结果,生产处理则应围绕事务状态和业务一致性目标进行。