Kafka是大型架构核心,下面我详解Kafka消息重复根本原因@mikechen
生产者端重试机制导致的重复
原因:生产者在发送消息失败(如网络抖动、超时),时会重试发送。
而若服务器实际上已成功接收但未及时返回确认,重试会产生重复消息。

解决方案:
启用生产者幂等性(enable.idempotence=true),以利用 producerId 和序列号保证单个分区内的准确一次。
合理配置重试次数与超时(retries、delivery.timeout.ms),以及配合幂等性,可实现更强的端到端重复控制。
消费者端处理失败与重复提交偏移量
消费者在处理消息后,提交 offset 之前发生故障(或在提交后处理崩溃)。
可能导致相同消息被重复消费、或跳过。
以及,手动与自动提交策略不当,都会引入问题。

解决方案:采用“先处理后提交”或“先提交后处理”需根据业务语义选择更安全的顺序。
使用精确控制的手动提交(enable.auto.commit=false)并在确保处理成功后提交 offset。
结合事务性消费者或外部持久化(如将处理结果与位移写入同一事务/数据库)以实现处理与位移原子性。
分区与副本机制引起的重复
在 leader 切换、ISR(In-Sync Replica)不同步或网络分区恢复时。
未正确处理的复制状态可能导致已提交的写入被重复或回滚后重发,产生重复或丢失。
解决方案:配置合适的复制因子和 min.insync.replicas 以保证写入的可靠性。

使用 ack=all(acks=all)确保所有同步副本确认。
监控 ISR 状态并优化网络与 broker 配置,尽量减少 leader 频繁切换。
必要时结合事务以确保跨分区/跨主题操作的一致性。
幂等性和去重策略不足
原因:系统端未设计端到端幂等或缺乏全局唯一的消息标识。
使得在重试或重放场景下无法辨识并去重,业务层被动承担复杂去重逻辑。

解决方案:在消息中携带全局唯一 ID(如 UUID、业务主键加时间戳或序列号)。
消费端实现基于外部存储(Redis、数据库)、或布隆过滤器的幂等检查。
对于高吞吐场景,采用精心设计的去重窗口或基于事件溯源的补偿机制。
尽可能将幂等性设计为业务操作本身(幂等 API、幂等写入语义)。
mikechen睿哥
10年+一线大厂架构实战经验,就职于阿里、淘宝等一线大厂,操盘多个亿级大厂核心项目。