fanout backlog 每条记录重复 seek 诊断¶
现象¶
隔离 Redis + Redpanda 功能验收在第 15 项登录对账失败:writer 的 commit hash 已是 COMMITTED 且含 outbox publication,但发送者与收件人都没有 mailbox key。
失败时指标:
- canonical commit:48
- fanout 已消费 Outbox:17
- mailbox 已物化 dispatch:34
qim_materialize_error_total = 0
继续等待 10 秒后:
- canonical commit 仍为 48
- fanout 已消费 Outbox:37
- mailbox 已物化 dispatch:74
即链路没有丢失或损坏,而是 fanout 稳定地只处理约 2 条 Outbox/s;验收前面的限流突发产生 backlog 后,最后一条消息在 5 秒对账窗口内无法到达。
根因¶
RdkafkaCommitLog::read_committed 的 positioned_after 只在显式 seek(after + 1) 时更新,正常 poll 成功后没有更新为刚消费的 source。
因此状态序列为:
- 消费 offset 0,但
positioned_after仍是None。 - 调用方传
after=0,执行 seek 到 1。 - 消费 offset 1,但
positioned_after仍是 0。 - 调用方传
after=1,再次 seek 到 2。
每条消息都触发一次 broker seek/重新取数,吞吐退化到约 2 msg/s。此前“相同 after 的空轮询不重复 seek”只修复了空闲饥饿,没有覆盖连续 backlog。
修复¶
- 每次成功 poll 并验证 source 后,把
positioned_after更新为该 source。 - 下一轮调用方传回同一 source 时继续顺序 poll,不 seek。
- 只有初始显式恢复位置或调用方主动向前跳转时才 seek;回退仍拒绝。
- 增强真实 Redpanda ignored 集成测试:连续发布并消费 24 条记录,5 秒内全部完成,防止每条记录 seek 回归。
验证¶
qim-commit-log单测与 clippy。- 隔离 Redpanda ignored 测试。
- 完整 15 项功能 smoke,登录对账必须命中发送者条目的
client_message_id。