来源:mikechen的互联网架构
Kafka如何保证消息不被重复消费,这是生产环境经常面临的问题,也是大厂重点考察内容,下面我就全面来详解Kafka如何保证消息不被重复消费
消息重复消费
重复消费是指消息系统中的消费者,例如:(消息队列中的消费者),在某些情况下会多次接收、并处理同一条消息。
一句话总结,就是已经处理过的消息,会被“多次”处理,从而导致重复的操作。
如果消费的是你的支付宝余额,也就是说你的余额,本只扣一次钱的,会被扣多次钱。

所以,消息重复消费,在实际的业务开发中,是需要重点关注的。
重复消费的原因
为什么会出现这样的情况呢?原因如下:

1.消息确认机制问题
消费者在处理消息后,需要向消息队列确认已经成功处理了该消息。
如果确认机制有问题,比如:在处理成功后未能正确发送确认信号,消息队列会认为该消息未被处理,从而再次发送。
2.消费者故障
在消息处理过程中,如果消费者出现故障(如:崩溃、网络异常...等),且未能完成确认,也会出现这样的情况。
3.消息队列问题
例如:某些消息队列在重启、或恢复后,可能会重复发送未确认的消息。
重复消费解决方案
这里的核心,就是确保消费者业务逻辑具有幂等性,无论同一个请求执行多少次,结果都是一致的。
如下图所示:

确保消费者业务逻辑具有幂等性,即无论同一个请求执行多少次,结果都是一致的。
具体的解决方案有很多,可以结合自己的业务来定,比如:唯一标识符、更新操作代替插入操作、设计幂等操作.......等逻辑来处理。
比如,还可以使用去重表:
CREATE TABLE orders (id INT AUTO_INCREMENT PRIMARY KEY,order_id VARCHAR(32) NOT NULL,status VARCHAR(50) NOT NULL,created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP);CREATE TABLE processed_orders (order_id VARCHAR(32) PRIMARY KEY,processed_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP);
大致流程,如下:
1、创建去重表
去重表用于记录已经处理过的操作ID,(如:消息ID、订单ID....等);
2、检查去重表
在处理操作之前,首先检查去重表中是否存在该操作ID,如果存在,说明该操作已经处理过,可以跳过处理;
3、处理操作
如果去重表中不存在该操作ID,则进行实际的业务处理;
4、记录操作
然后,业务处理完成后,将操作ID记录到去重表中。
以上只是一种思路,核心是关注数据的唯一性校验,这才是本质。
大家可以想想这种方案有哪些问题?如何来改进?
比如:在高并发场景下,多个请求可能同时查询和插入去重表,导致并发问题,如何来改进?
以上