Kafka如何保证消息不被重复消费?

来源: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记录到去重表中。

以上只是一种思路,核心是关注数据的唯一性校验,这才是本质。

大家可以想想这种方案有哪些问题?如何来改进?

比如:在高并发场景下,多个请求可能同时查询和插入去重表,导致并发问题,如何来改进?

以上


请使用浏览器的分享功能分享到微信等