重复消费是大厂经常涉及的,下面我详解Kafka重复消费解决方案@mikechen
一、先理解为什么会重复消费
Kafka 消息重复消费通常由以下几类原因导致:

消费者提交 Offset 失败;
消费成功后,Offset 尚未提交,服务就宕机了,重启后会重新消费;
分区重新分配时,某些消息可能被新消费者再次拉取;
业务处理成功,但提交 Offset 前失败..。等等,都会造成重复消费。
Kafka如何来解决?
常见实现方式:

(1)唯一业务主键去重
为每条消息生成唯一标识,例如:
订单号;
流水号;
事件 ID;
全局唯一消息 ID;
消费时先查询该 ID 是否已处理:
已处理:直接忽略;
String uniqueKey = message.getOrderId() + "_" + message.getVersion();
if (redisTemplate.opsForValue().setIfAbsent(uniqueKey, "1", 7, TimeUnit.DAYS)) {
// 未消费过,执行业务逻辑
processBusiness(message);
} else {
log.info("消息已消费,跳过: {}", uniqueKey); // 重复消费,直接忽略
}
未处理:执行业务并记录处理结果
(2)数据库唯一约束

将消息 ID 写入处理表,并对该字段加唯一索引。
| message_id | status | consume_time |
|---|---|---|
| xxx001 | 1 | 2026-xx-xx |
如果重复插入,数据库会直接拒绝。
(3)状态机控制
适用于订单、支付、库存等场景。
例如订单状态只能从“待支付”流转到“已支付”,重复消息再次执行时会因状态不匹配而被拒绝。
优点:

通用性强;
对 Kafka 配置依赖小;
最符合分布式系统设计原则
缺点:
需要业务系统支持;
设计复杂度相对更高。