订阅更新

Kafka read_committed 为什么读不到最新消息?LSO 和 HW 有什么区别?

面试问 236 约 3 分钟读完

本文目录
  1. 面试怎么回答
  2. 先统一位点表示,避免差一争论
  3. LSO 会被最早未结束事务挡住
  4. readcommitted 不保证业务处理恰好一次
  5. 一个典型场景:消费积压来自没结束的事务
  6. 排查要把三种进度放在一起
  7. 参考资料

面试怎么回答

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,这会改变业务可见性并暴露可能中止的事务数据。可以在独立诊断环境比较两种读取结果,生产处理则应围绕事务状态和业务一致性目标进行。

参考资料

刷题进度保存在当前浏览器