已采纳
回答正文
回复
讨论正文
该问题的正文、回答与讨论。
背景
Kafka 3.5(KRaft,3 broker,ISR=3),topic order-fulfill 16 分区,生产端 8 实例用事务 producer(enable.idempotence=true + transactional.id=fulfill-{shard},transaction.timeout.ms=60000),每笔事务打包「MySQL 8.0 订单状态 UPDATE + 发 1~3 条 fulfill 消息」。消费端 4 实例,isolation.level=read_committed。
现象
上周压测后,我在 staging 上做过一次破坏性演练:producer 实例在 commitTransaction() 发出后、commitResponse 返回前被 kill -9(模拟节点 OOM 被内核杀)。之后 60 秒内:
poll() 全部返回空,position() 停在 LSO 上不动;kafka-consumer-groups --describe 显示 group lag 正常(current offset 不动,log end offset 在涨),常规 lag 告警一条都没触发;已尝试的排查
kafka-metadata 查 __transaction_state,确认了 aborted 事务在 timeout 到期前 LSO 就是被压住的,语义没跑偏;read_committed 和 read_uncommitted 各起一个,每分钟 position() 对比,差值 > 0 就告警。问题:read_uncommitted 的 position 在悬挂事务后到底是「越过 aborted 段」还是「停在段尾」?我实测两种结果都出现过,怀疑跟 aborted 事务是否已 fence 有关,拿不到一个稳定的口径;AbortedTransactionCount,但它是累计值,没有「当前悬挂中」的语义,而且要看的是 __transaction_state 里的活跃 aborted 记录数,这个指标在标准 exporter 里我没有找到直接暴露的。期望得到的答案形态
transaction.timeout.ms 窗口内,提前(比如 30s 时)就能告警的手段——是扫 __transaction_state、还是 LSO/LEO 双消费组对比、还是 broker 指标,各方案的坑在哪?transaction.timeout.ms 从 60s 压到 15s 的风险边界:会不会把「正常但慢的事务」误 fence?你们线上这个值是怎么定的?read_uncommitted + 业务幂等兜底)?还是说这条路本身不推荐?参考:《Kafka read_committed 消费端被悬挂事务卡 90 秒:LSO/LEO 语义与定位命令全记录》(id=574)、《Kafka 事务生产者 initTransactions 永久挂起:transactional.id 复用与 15 分钟事务上限的根因与清理》(id=1028)。