高频面试题|RabbitMQ如何防止消息的重复消费?

news2024/12/27 17:28:58

一. 前言

最近有很多小伙伴开始找工作,在面试时,面试官经常会问我们这样一个题目:

RabbitMQ如何防止重复消费?

有很多小伙伴这个时候都在想,消息怎么还会重复消费呢???.......

所以他们在面试后就跑来问壹哥,针对这个比较高频的题目,壹哥就在这里为大家来讲讲MQ防止重复消费的实现方案吧。

二. 面试题考点

如果面试官是壹哥的话,那么我想考察的,其实是候选人对技术的基本使用,以及在各种实际应用场景中对可能发生的问题的实际处理能力。所以这道题的考点,最起码要考虑两点:

第一,RabbitMQ中消息的重复消费是如何产生的?我们首先要发现问题,知道问题产生原因;
第二,针对重复消费问题的处理方案及解决机制。

三. 解题分析

接下来壹哥就根据上述考点,带大家来一起分析这个问题的解题思路。

1. RabbitMQ消息重复消费的产生原因

根据上图,壹哥给大家梳理总结出了消息可能出现重复消费的产生过程,如下:

1. 消费方的业务项目从MQ队列中接收数据;
2. 接着处理业务;
3. 业务处理成功后,消费方项目给MQ返回ack进行手动确认;
4. 返回回调执行结果的过程中,因为网络抖动等原因,回调数据时,MQ没有返回成功。所以MQ队列中的数据会再次发给业务项目,造成重复消费。

2. RabbitMQ消息重复消费的处理方案

针对消息的重复消费问题,壹哥根据上图总结的解决思路如下:

1. 监听器接收MQ队列中的数据;
2. 利用redis的setnx命令,以消息唯一id为key,以消息内容为value,超时时间设置为10秒,存入redis中;
3. 如果能够成功存入,说明没有重复消费,则处理业务,处理完业务后返回ack或者nack确认;
4. 如果存不进去,则说明重复消费,直接返回ack确认的回调信息就可以了。

3. 解决重复消费的案例代码

3.1 发送方测试代码

/**
 * 测试发送
 * @author 千锋壹哥
 */
@SpringBootTest(classes = ProducerApplication.class)
@RunWith(SpringRunner.class)
public class TestProducer {

    @Autowired
    private RabbitTemplate rabbitTemplate;

    @Test
    public void contextLoads() throws IOException {
        //给消息封装一个唯一id对象
        CorrelationData messageId = new CorrelationData(UUID.randomUUID().toString());
        //第四个参数: 设置消息唯一id
        rabbitTemplate.convertAndSend("交换器名字","路由键","千锋壹哥测试MQ重复消费处理!!",messageId);
    }
}

3.2 接收方测试代码

package com.qf.rabbitmq.topic;

import com.rabbitmq.client.Channel;
import org.springframework.amqp.core.Message;
import org.springframework.amqp.rabbit.annotation.RabbitListener;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.stereotype.Component;

import java.io.IOException;
import java.util.concurrent.TimeUnit;

/**
 * @author 千锋壹哥
 */
@Component
public class Consumer {

    @Autowired
    private StringRedisTemplate redisTemplate;

    @RabbitListener(queues = "队列名字")
    public void getMessage(String msg, Channel channel, Message message) throws IOException {
        //0. 获取MessageId, 消息唯一id
        String messageId = (String) message.getMessageProperties().getHeaders().get("spring_returned_message_correlation");
        //1. 设置key到Redis
        if(redisTemplate.opsForValue().setIfAbsent(messageId,"0", 10, TimeUnit.SECONDS)) {

            //2. 消费消息
            System.out.println("接收到消息:" + msg);

            //3. 设置key的value为1
            redisTemplate.opsForValue().set(messageId,"1",10,TimeUnit.SECONDS);

            //4.  手动ack
       channel.basicAck(message.getMessageProperties().getDeliveryTag(),false);
        }else {
            //5. 获取Redis中的value即可 如果是1,手动ack
          if("1".equalsIgnoreCase(redisTemplate.opsForValue().get(messageId))){
                channel.basicAck(message.getMessageProperties().getDeliveryTag(),false);
            }
        }
    }
}

四. 总结

经过上面的分析,最后壹哥再给大家总结一下这个问题的完整答案。

1.问题产生原因

因为消费方和MQ服务器网络闪断等原因,造成了接收方接受消息后,返回给MQ服务器一个ack确认消息,但MQ却没有接收到,这就造成了重复消费。

2.解决过程

利用redis的setnx命令,将消费的消息id存入到redis,超时时间设置为10秒,然后再给mq返回ack。消费前要判断redis中是否存在这个消息id,如果不存在说明没有消费过,则正常消费;如果redis中存在这个消息id,则说明产生了重复消费,此时直接返回ack,不重复执行业务。

如果你想知道更详细的解答,可以参考壹哥的高薪面试题精讲专栏哦:

高薪程序员&面试题精讲系列125之RabbitMQ怎样保证消息的可靠性、不重复及不丢失?

以上就是MQ中,消息重复消费的产生原因及解决思路和对应案例,现在你知道该怎么解决了吗?如果你还有其他疑问,可以在评论区给我们留言哦。关注壹哥,收获多多!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/374459.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

【华为OD机试模拟题】用 C++ 实现 - 异常的打卡记录(2023.Q1)

最近更新的博客 【华为OD机试模拟题】用 C++ 实现 - 去重求和(2023.Q1) 文章目录 最近更新的博客使用说明异常的打卡记录【华为OD机试模拟题】题目输入输出备注示例一输入输出说明示例二输入输出说明示例三输入输出说明

基于合作型Stackerlberg博弈的考虑差别定价和风险管理的微网运行策略研究(Matlab代码实现)

💥💥💞💞欢迎来到本博客❤️❤️💥💥 🏆博主优势:🌞🌞🌞博客内容尽量做到思维缜密,逻辑清晰,为了方便读者。 ⛳️座右铭&a…

数据结构与算法(五):优先队列

这节总结一下优先队列的常用实现方法。 一、基本概念 普通的队列是一种先进先出的数据结构,元素在队列尾追加,而从队列头删除。在优先队列中,元素被赋予优先级。当访问元素时,具有最高优先级的元素最先删除。优先队列具有最高级…

100天精通Python(数据可视化篇)——第77天:数据可视化入门基础大全(万字总结+含常用图表动图展示)

文章目录1. 什么是数据可视化?2. 为什么会用数据可视化?3. 数据可视化的好处?4. 如何使用数据可视化?5. Python数据可视化常用工具1)Matplotlib绘图2)Seaborn绘图3)Bokeh绘图6. 常用图表介绍及其…

81页5G 智慧工厂物联数字孪生可视化建设方案

数字企业建设思路3 XXXX智慧企业将以信息化为基础、以数据为纽带、以制造为核心、以管理为载体打造新型智慧园区,该智慧园区整合了企业的安全、环保、能源、安防、应急、服务等数据资源,支撑企业科学、准确、及时决策,提升企业综合监管能力、…

计算机网络笔记、面试八股(一)—— TCP/IP网络模型

本章目录1. TCP/IP网络模型1.1 应用层1.1.1 应用层作用1.1.2 应用层有哪些常用协议1.2 运输层1.2.1 TCP与UDP的区别1.2.2 分块传输1.2.3 端口1.3 网络层1.3.1 IP报文1.3.2 IP地址1.3.3 网络号和主机号的获得1.3.4 子网掩码的获得1.3.5 路由1.3.6 IP地址与MAC地址的区别1.3.7 AR…

【C++】List 基本接口的使用

LISTList 基本接口介绍前言list 构造方法list 析构方法容量相关元素获取迭代器元素的修改其他相关操作前边博客中已经介绍了c STL 中的 string 以及 vector 基本接口的使用方法并进行了接口的模拟实现,接下来让我们来学习 list 的基本接口使用方法吧~~ List 基本接…

Linux基础命令-stat显示文件的状态信息

文章目录 stat 命令介绍 语法格式 基本参数 测试三个时间的变化过程 1)使用cat命令 2)使用echo命令 3)使用chmod命令 4)使用vim命令 参考实例 1)显示文件的状态信息 2)以简洁的形式显示状态信…

Android:IdleHandler的简单理解和使用

IdleHandler的简单理解和使用1、IdleHandler 是什么2、IdleHandler 使用方式2.1、添加和删除2.2、执行3、常见问题和使用场景3.1、使用场景3.2、常见问题参考1、IdleHandler 是什么 IdleHandler 说白了,就是 Handler 机制提供的一种,可以在 Looper 事件…

Cesium 100K数据加载 支持弹窗 动态更改位置

前言:今天总结关于point、label、billboard海量数据加载。后续会研究下大量model加载以及大bim(几百G上T)模型记载 海量点加载 弹窗 加载点位时,不加载弹窗。点击点位时在加载弹窗,及有效的减少加载量,优化性能。 const handler …

FPGA学习之日常工作复位电路

最近一个多月没有写博客了,然后最近工作中也遇到一个复位信号的问题。问题是这样的,关于外部复位信号,之前我们的处理方式都是通过PLL产生的Lock信号作为内部的复位信号。但是由于换到A54上面没有IP核,所以只有不用PLL&#xff0c…

Mybatis持久层框架 | 动态SQL、缓存

💗wei_shuo的个人主页 💫wei_shuo的学习社区 🌐Hello World ! 动态SQL 动态SQL就是指根据不同条件生成不同的sql语句,本质还是SQL语句,知识可以在SQL层面,执行逻辑代码 搭建环境 创建数据库 cre…

Linux搭建SVN服务器,并内网穿透实现公网远程访问

文章目录1. Ubuntu安装SVN服务2. 修改配置文件2.1 修改svnserve.conf文件2.2 修改passwd文件2.3 修改authz文件3. 启动svn服务4. 内网穿透4.1 安装cpolar内网穿透4.2 创建隧道映射本地端口5. 测试公网访问6. 配置固定公网TCP端口地址6.1 保留一个固定的公网TCP端口地址6.2 配置…

HCIA-HarmonyOS Application Developer——题目集2

题目1 1、HarmonyOS的"18N”战略中的"1"指的是什么? A、智慧屏 B、平板电脑 C、手表 D、手机 解析:(D) HarmonyOS是一款面向万物互联时代的、全新的分布式操作系统,是一个全场景分布式智慧操作系统,覆…

从产品经理的角度如何提升项目的交付质量?

提高交付质量 ,对于每个IT公司都是永恒的话题。 交付质量其实包含2重意义, 一是交付的高质量(客户角度),即客户的满意度;二是高质量的交付(交付团队的角度),这里是指如何…

【笔记】ChatGPT是怎样炼成的(李宏毅2023机器学习课程引入部分)

来源:【授权】李宏毅2023春机器学习课程 ChatGPT太火热了,借此简单了解一下 ChatGPT的newbie之处在哪里? 同一个问题,它的每次回答都不同;处于同一个chat中,我可以追问多个问题,因为它知道上下…

NO.8代码随想录第8天-字符串|●28. 实现 strStr()●459.重复的子字符串●字符串总结

KMP算法的原理: KMP算法:解决字符串匹配的问题。 前缀:包含首字母不包含尾字母的所有子串。 后缀:包含尾字母不包含首字母的所有子串。 最长相等前后缀:以模式串aabaaf为例,这里从a开始到aabaaf&#x…

数据结构入门DAY1

力扣刷题合集:力扣刷题_Sunlightʊə的博客-CSDN博客217.存在重复元素相关题目链接:力扣 - 存在重复元素题目重现给你一个整数数组 nums 。如果任一值在数组中出现 至少两次 ,返回 true ;如果数组中每个元素互不相同,返…

【Spark分布式内存计算框架——Spark Streaming】5. DStream(上)

3. DStream SparkStreaming模块将流式数据封装的数据结构:DStream(Discretized Stream,离散化数据流,连续不断的数据流),代表持续性的数据流和经过各种Spark算子操作后的结果数据流。 3.1 DStream 是什么…

镜像、复制和直线绘制CAD图形

这个CAD图形可以分成两个部分:上面一部分和下面一部分,都是有多个相同的对象,所以只需要绘制出其中一个再使用复制和旋转命令将其它的绘制出就可了,用到的主要CAD命令有CAD直线、CAD旋转、CAD镜像和CAD直线 目标对象 操作步骤 1…