标准答案
- 先提交位点再处理,消费者崩溃后会从新位点继续,未完成的消息可能丢失,适合允许丢失或业务副作用很弱的场景。
- 处理成功后再提交,崩溃窗口会导致消息重新投递,因此业务处理必须能安全重复。
- 如果消息系统和目标存储支持同一事务,可以把业务写入与位点提交放在事务边界内;跨系统时通常仍需 Outbox、幂等记录或补偿。
- 失败消息不应盲目提交跳过,应区分可重试错误、不可重试错误和需要人工处理的毒性消息。
题目解析
位点只表示消费者已经确认到哪个位置,不能直接证明目标数据库、缓存或外部服务已经完成业务副作用。提交得太早可能丢消息,提交得太晚则允许重复处理。
常见的至少一次方案是先完成可重试的业务处理,再提交位点,并用唯一约束、幂等记录或状态机吸收崩溃窗口。若消息和目标存储支持同一事务,才能把两者纳入同一提交边界。
失败处理还要区分暂时错误、永久错误和毒性消息。无限重试会阻塞分区、放大下游压力,跳过消息又可能造成业务缺口,必须保留可查询和可恢复的证据。
常见误区
- 误区:把提交位点当成业务事务提交。改正:位点和副作用是两个状态,跨系统时要靠幂等、Outbox 或补偿连接它们。
- 误区:失败后无限重试同一条消息。改正:设置退避和次数上限,超过阈值进入死信或人工处理。
- 误区:没有为重复处理设计唯一约束或幂等记录。改正:保存事件 ID、业务键和处理结果,让重复消费可以安全结束。