记录一次生产事件
现象:放入消息队列的一条消息推送到了消费者的2个实例上,两条消息接收到消息的时间间隔在几毫秒之内(一共三个实例)
在测试环境中由于部署的服务是单个结点,投产时也没有准生产环境,导致,上了生产后,偶尔会出现消息重复推送问题。
项目当中使用的中间件是RocketMq,版本是4.7.1,部署方案是三主三从,一个服务有三个结点
1. 一开始,创建表的时候虽然加了消息主键作为唯一索引,但是生成主键的地方写在了消费者这边,导致MQ消费者这边收到了两条一样的消息还能正常入库。
2. 后来,把生成消息主键的地方放在了生产者那边,这样即使有两条消费者以后,第二条数据就通过数据库的主键索引给拦住了。
3. 但是,线上运行一段时间后,发现重复推送的情况还比较多,这样日志里面会有很多报重复主键插入失败的异常,不雅!!!
4. 最终引入Redis解决方案:
利用redis提供的setIfAbsent方法通过redis进行拦截如果30s内重复推送,则终止执行。
Boolean existKey = redisTemplate.opsForValue().setIfAbsent("msgId", "", 30, TimeUnit.SECONDS); //如果redis中不存在msgId key则放入成功返回true,执行业务逻辑,否则终止。 if(!existKey){ logger.error("mq重复推送请检查!!!"); return; }else{ //执行业务逻辑...... }
不知道大家遇到过没!!!