【消息队列】保证消息消费的幂等

昨天业务反馈了一个问题,一个用户的月流水账单重复了,拿到userid,开始定位问题之路。

查看数据库记录,如下图,用户月流水数据确实重复了(taskid同一个批次,每个月数据都有二条)。

1. 首先,看外部数据供应商是否重复推送业务数据给我,我程序中是会设置拦截重复消息

2. 查看消息接收,以及消息推送到MQ

消息接收

消息推送

看下来前面的步骤都没有重复,再看消息的消费,如下图所示:

 原因定位:看是消费端消费了MQ中的同一条消息消费了二次,这个发生时间正好在我们上线时间,也就是上线的时候会发生消息重复消费,因为一个消息被处理之后,没来得及提交offset消费线程就被kill掉了,然后重启之后从MQ拿的消息还是之前的消息,当然好处是保证每条消息都保证至少会消费一次,缺点是消息可能会重复消费。

解决方案:1. 对于流程中的消息,每条消息中包含唯一id,比如业务id,在数据库中将业务id作为Unique key,插入重复时会报duplicate key异常;

2. redis中存储业务id,重复的时候set一下,任务丢弃,redis的key失效时间可以设置的很短,因为重复消费的一般发生间隔时间非常短。

欢迎关注Java流水账公众号
原文地址:https://www.cnblogs.com/guofu-angela/p/10900013.html