MQ的初步了解

目录

什么是MQ?

为什么要用MQ(MQ的优点)?

MQ的缺点

常用的MQ产品

MQ使用中的常见问题


什么是MQ?

  【1】MQ:MessageQueue,消息队列。 队列,是一种FIFO 先进先出的数据结构。消息由生产者发送到MQ进行排队,然后按原来的顺序交由消息的消费者进行处理。QQ和微信就是典型的MQ。

消息队列(MQ)是一种用于在不同组件或系统之间传递消息的通信方式。它是一种在分布式系统中广泛使用的技术,用于解耦生产者和消费者,以实现异步通信,提高系统的可伸缩性和可靠性。

MQ的主要特点和优势包括:

  1. 解耦和异步通信:生产者和消费者之间通过MQ进行通信,不需要直接互相调用,从而解耦了系统组件,使系统更加灵活和可维护。同时,MQ支持异步通信,消费者可以在需要的时候处理消息,而不需要等待生产者的响应。

  2. 消息持久化:MQ通常支持消息的持久化,即使在生产者发送消息后,即使消费者当前不可用,消息也不会丢失。

  3. 负载均衡:MQ可以轻松实现多个消费者之间的负载均衡。多个消费者可以订阅相同的消息队列,并同时处理消息,以提高处理能力。

  4. 消息广播:MQ通常支持一对多的消息传递,使得消息可以广播给多个消费者。

  5. 消息过滤:MQ允许消费者根据消息的内容或属性来进行过滤,只选择他们关心的消息。

  6. 确保消息可靠性:MQ通常具有消息确认机制,确保消息能够可靠地传递到消费者。

  7. 缓冲:MQ可以充当缓冲,帮助平衡生产者和消费者之间的速度差异,防止消息丢失。

常见的消息队列系统包括RabbitMQ、Apache Kafka、ActiveMQ、Amazon SQS等。它们在不同场景下具有不同的特点和适用性,可以根据具体需求选择合适的MQ系统来构建分布式应用。

为什么要用MQ(MQ的优点)?

  MQ的作用主要有以下三个方面:

  【1】异步

    例子:快递员发快递,直接到客户家效率会很低。引入菜鸟驿站后,快递员只需要把快递放到菜鸟驿站,就可以继续发其他快递去了。客户再按自己的时间安排去菜鸟驿站取快递。

    作用:异步能提高系统的响应速度、吞吐量。

  【2】解耦

    例子:《Thinking in JAVA》很经典,但是都是英文,我们看不懂,所以需要编辑社,将文章翻译成其他语言,这样就可以完成英语与其他语言的交流。

    作用:

      1、服务之间进行解耦,才可以减少服务之间的影响。提高系统整体的稳定性以及可扩展性。

      2、另外,解耦后可以实现数据分发。生产者发送一个消息后,可以由一个或者多个消费者进行消费,并且消费者的增加或者减少对生产者没有影响。

  【3】削峰

    例子:长江每年都会涨水,但是下游出水口的速度是基本稳定的,所以会涨水。引入三峡大坝后,可以把水储存起来,下游慢慢排水。

    作用:以稳定的系统资源应对突发的流量冲击。

MQ的缺点

  【1】系统可用性降低

    系统引入的外部依赖增多,系统的稳定性就会变差。一旦MQ宕机,对业务会产生影响。这就需要考虑如何保证MQ的高可用。

  【2】系统复杂度提高

    引入MQ后系统的复杂度会大大提高。以前服务之间可以进行同步的服务调用,引入MQ后,会变为异步调用,数据的链路就会变得更复杂。并且还会带来其他一些问题。比如:如何保证消费不会丢失?不会被重复调用?怎么保证消息的顺序性等问题。

  【3】消息一致性问题

    A系统处理完业务,通过MQ发送消息给B、C系统进行后续的业务处理。如果B系统处理成功,C系统处理失败怎么办?这就需要考虑如何保证消息数据处理的一致性。

尽管消息队列(MQ)是一种强大的工具,可以提供许多优势,但它也存在一些潜在的缺点和挑战,包括:

  1. 复杂性:配置和管理消息队列系统可能会相当复杂,尤其是在大规模和高可用性环境下。这可能需要专业知识来确保系统的正确配置和运行。

  2. 维护成本:维护和监控消息队列系统需要额外的资源和时间。需要考虑到消息队列服务器的升级、备份、监控和故障处理等问题。

  3. 一致性问题:在分布式系统中,确保消息的一致性可能会变得复杂。例如,在消息发布后,如果在消息处理之前发生故障,可能会导致消息的丢失或重复处理。

  4. 消息堆积:如果消息队列系统的消费者速度不足以处理消息的生产速度,消息可能会在队列中堆积,导致延迟和系统性能问题。

  5. 消息顺序问题:某些消息队列系统可能无法保证消息的严格顺序。虽然大多数MQ系统可以提供有序消息,但在某些情况下可能需要额外的努力来确保消息的顺序性。

  6. 部署和维护成本:引入MQ系统需要额外的硬件和网络资源,以及相应的运维工作。这可能会增加部署和维护的成本。

  7. 学习曲线:对于新手来说,学习如何使用特定的MQ系统可能需要一定的时间和培训,尤其是对于复杂的系统和配置。

  8. 安全性:消息队列中的消息可能包含敏感信息,因此需要特别关注安全性。必须采取措施来加密和保护消息,以防止未经授权的访问。

常用的MQ产品

  【1】Kafka、RabbitMQ和RocketMQ。我们对这三个产品做下简单的比较,重点需要理解他们的适用场景。

  【2】图示:

                  

   【3】分别分析三种消息中间件

    1.RabbitMQ:消息可靠性很高,功能非常全面,很多高级功能都是从这里衍生出来的,如死信队列,延迟队列。缺点在于吞吐量很低,消息积累会影响消费的性能,而且erlang的语言使用的比较少,定制比较难。适用于公司内部系统的请求扭转的流程。

    2.Kafka:行业的老大哥,基本上是大数据场景必用的组件之一,吞吐量不可挑战,集群性能很好。之前是依赖zookeeper搭建集群,但是新版本会逐渐抛弃zookeeper。但是会存在丢消失的可能,而且功能单一,很多高级功能都没有,如死信队列。最早就是用来做日志分析的。

    3.RocketMQ:最开始是借鉴Kafka,后面逐步优化。吞吐量基本和Kafka是一个量级的,功能也很全面,如RabbitMQ有的都有,还有其他没有的事务功能。缺点是开源版不如云上商业版。如延迟队列,开源会有固定的限制。

MQ使用中的常见问题

  【1】如何保证消息不丢失

    1)分析哪些环节会有丢消息的可能

      (1)图示

           

      (2)分析

        1.其中,1,2,4三个场景都是跨网络的,而跨网络就肯定会有丢消息的可能。

        2.而3这个环节,通常MQ存盘时都会先写入操作系统的缓存page cache中,然后再由操作系统异步的将消息写入硬盘。这个中间有个时间差,就可能会造成消息丢失。如果服务挂了,缓存中还没有来得及写入硬盘的消息就会丢失。这也是任何用户态的应用程序无法避免的。

    2)分析怎么处理的

      1.为保证消息不丢失,发送端的ACK应答必须是多个节点写入的应答 兼 采用多次重试的方式(预防网络抖动),其次消息中间件内部持久化,消费端是消费后手动应答。

      2.在发送端还应该:区分业务的关键性,如果消息不影响主体业务(如,消息通知要做的事情可以延迟很久,但因某些缘故,消息发不出去),这时候采用将消息落盘,然后调用定时任务的形式,延时检查发送。

      3.在消费端还应该:对消费失败的消息进行次数检测,如果多次失败(有可能参数异常,有可能流程出了问题),应该落盘(避免消息堆积),告知程序员处理。

  【2】如何保证消息幂等性

    1)分析哪些环节会造成消息重复消费

      1.MQ的自动重试功能:如网络抖动时,生产者发送得不到MQ的回应尝试多次发送;消费者做完任务,返回给MQ的应答丢失,导致MQ发给了另一个消费者去消费消息。

      2.代码BUG导致消息多次发送。

    2)分析怎么处理的

      1.首先在MQ上我们是不能保证消息的幂等性的,所以我们只能在业务中处理。

      2.处理幂等问题的关键是要给每个消息一个唯一的标识(但这个不能是MQ给我们的消息ID,因为它依旧解决不了生产者发送多次的问题)

      3.需要我们自行构建分布式唯一ID(如雪花算法),能够添加一个具有业务意义的数据作为唯一键会更好,这样能更好的防止重复消费问题对业务的影响。比如,针对订单消息,那就用订单ID来做唯一键。

      4.如订单ID来做唯一键,就算真的出现了很不幸的两个消费者同时消费两条重复的数据,那么在进行MYSQL写入的时候,事务处理与唯一键索引,将是兜底保证业务执行幂等性的关键。

      5.当然,采用redis的Setnx(要设置超时时间)作为CAS锁保证只有一个线程执行业务也是可以的,成功后还可以设置标记值来标记该业务已经做完,等下次重复的消息过来时候,进行redis检验的时候就会自动丢弃这些重复的消息。【这里面需要衡量的是业务的处理速度,与占用redis的内存空间,虽然有过期时间,但是在这段时间内这些数据依旧会占用空间,如果处理速度很快,则占用的空间越多

  【3】如何保证消息的顺序

    1)原因:某些场景下,需要保证消息的消费顺序,例如一个下单过程,需要先完成扣款,然后扣减库存,然后通知快递发货,这个顺序不能乱。如果每个步骤都通过消息进行异步通知的话,这一组消息就必须保证他们的消费顺序是一致的

    2)分析该怎么处理(基于MQ无法保证,那么更多是在业务层面实现

      方案一:为保证消息的有序性,采用用同步发送的模式去发消息,然后消息发往同一个队列里面,然后采用一个消费者去进行消费。

      方案二:为保证高性能,采用用异步发送的模式去发消息,然后消息发往同一个队列里面,然后采用一个消费者去进行消费。消费者端接收后,因为可能消息群是乱序的(异步发送模式),所以构建内存队列(优先级队列),将消息排序消费(每个内存队列只允许一个线程消费,可拓展为多个内存队列多个线程)

      针对这种,容易出现消息堆积的情况,可扩展为多个队列,每个队列都有唯一的一个消费者。在发送端建立消息组ID,根据组ID进行hash决定这一组消息分配至哪个队列里面。但是又容易出现数据倾斜的问题,则可以考虑构建hash环与增加虚拟节点的想法,将数据更加均匀的分布。

  【4】数据堆积如何处理

    1)线上有时因为发送方发送消息速度过快,或者消费方处理消息过慢,可能会导致MQ积压大量未消费消息。此种情况如果积压了上百万未消费消息需要紧急处理,可以修改消费端程序,让其将收到的消息快速转发到其他队列,然后再启动多个消费者同时消费。

    2)由于消息数据格式变动或消费者程序有bug,导致消费者一直消费不成功,也可能导致MQ积压大量未消费消息。此种情况可以将这些消费不成功的消息转发到其它队列里去(类似死信队列),后面再慢慢分析死信队列里的消息处理问题。

例子:

Java的RabbitMQ库为例来演示如何发布和消费消息

import com.rabbitmq.client.*;public class MessageQueueExample {private final static String QUEUE_NAME = "hello";public static void main(String[] args) throws Exception {// 创建连接工厂ConnectionFactory factory = new ConnectionFactory();factory.setHost("localhost"); // RabbitMQ服务器的主机名// 创建连接Connection connection = factory.newConnection();// 创建通道Channel channel = connection.createChannel();// 声明队列channel.queueDeclare(QUEUE_NAME, false, false, false, null);// 发布消息String message = "Hello, RabbitMQ!";channel.basicPublish("", QUEUE_NAME, null, message.getBytes());System.out.println(" [x] Sent '" + message + "'");// 创建消息消费者DeliverCallback deliverCallback = (consumerTag, delivery) -> {String receivedMessage = new String(delivery.getBody(), "UTF-8");System.out.println(" [x] Received '" + receivedMessage + "'");};// 消费消息channel.basicConsume(QUEUE_NAME, true, deliverCallback, consumerTag -> { });}
}

Spring Boot和Apache Kafka来发布和消费消息

生产者示例

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.kafka.core.KafkaTemplate;
import org.springframework.stereotype.Component;@Component
public class KafkaProducer {private static final String TOPIC = "my-topic";@Autowiredprivate KafkaTemplate<String, String> kafkaTemplate;public void sendMessage(String message) {kafkaTemplate.send(TOPIC, message);}
}

在这个示例中,我们创建了一个名为KafkaProducer的Spring组件,它使用KafkaTemplate来发送消息到名为"my-topic"的Kafka主题。

消费者示例

import org.springframework.kafka.annotation.KafkaListener;
import org.springframework.stereotype.Component;@Component
public class KafkaConsumer {@KafkaListener(topics = "my-topic", groupId = "my-group")public void consumeMessage(String message) {System.out.println("Received message: " + message);}
}

在这个示例中,我们创建了一个名为KafkaConsumer的Spring组件,它使用@KafkaListener注解来监听名为"my-topic"的Kafka主题,并在消息到达时执行consumeMessage方法。

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

如若内容造成侵权/违法违规/事实不符,请联系编程知识网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

基于SpringBoot的驾校管理系统

基于SpringBootVue的驾校管理系统、前后端分离 开发语言&#xff1a;Java数据库&#xff1a;MySQL技术&#xff1a;SpringBoot、Vue、Mybaits Plus、ELementUI工具&#xff1a;IDEA/Ecilpse、Navicat、Maven 【主要功能】 角色&#xff1a;管理员、用户、教练 管理员&#x…

Python 可迭代对象、迭代器、生成器

可迭代对象 定义 在Python的任意对象中&#xff0c;只要它定义了可以返回一个迭代器的 __iter__ 魔法方法&#xff0c;或者定义了可以支持下标索引的 __getitem__ 方法&#xff0c;那么它就是一个可迭代对象&#xff0c;通俗的说就是可以通过 for 循环遍历了。Python 原生的列…

【图论】有向图的强连通分量

算法提高课笔记 文章目录 理论基础SCC板子 例题受欢迎的牛题意思路代码 学校网络题意思路代码 最大半连通子图题意思路代码 银河题意思路代码 理论基础 什么是连通分量&#xff1f; 对于一个有向图&#xff0c;分量中任意两点u&#xff0c;v&#xff0c;必然可以从u走到v&am…

结构体成绩排序

任务描述 本关任务&#xff1a;有n个学生的信息(包括学号&#xff0c;姓名&#xff0c;成绩)&#xff0c;要求按照成绩的高低顺序输出学生的信息。 相关知识 参考结构体第1关相关知识 编程要求 在右侧编辑器Begin-End处补充代码&#xff0c;要求按照成绩的高低顺序输出学生…

【深度学习】 Python 和 NumPy 系列教程(廿七):Matplotlib详解:3、多子图和布局:散点矩阵图(Scatter Matrix Plot)

目录 一、前言 二、实验环境 三、Matplotlib详解 1、2d绘图类型 2、3d绘图类型 3、多子图和布局 1. subplot()函数 2. subplots()函数 3. 散点矩阵图&#xff08;Scatter Matrix Plot&#xff09; 一、前言 Python是一种高级编程语言&#xff0c;由Guido van Rossum于…

视屏点播项目

项目背景 大家应该在电脑上刷过视频吧,这个项目就是模拟一下我们刷视频的整个流程,我们要做的是一个类似B站的网页,这里面包含视频的上传修改和观看以及删除,注意我这个是一个简易版本的,在后面我会做一个升级,增加其他的功能. 基本原理 下面我们说一下我们项目的基本原理.我…

如何根据性能需求进行场景设计?

场景设计一 探索 测试环境 客户端: win10 这里可以用linux,但没用,因为想直观查看结果。 被测环境:linux X86 4核CPU16G内存 被测接口:登录接口,没有做数据驱动。 在测试执行前,先使用influxSQL把influxdb的数据清理一下,以防影响结果查看。 有这么一个需求,要求系…

Android 12 源码分析 —— 应用层 五(SystemUI的StatusBar类的启动过程和三个窗口的创建)

Android 12 源码分析 —— 应用层 五&#xff08;SystemUI的StatusBar类的启动过程和三个窗口的创建&#xff09; 在前面的文章中&#xff0c;我们介绍了SystemUI App的基本布局和基本概念。接下来&#xff0c;我们进入SystemUI应用的各个UI是如何被加入屏幕的。那么我们就先从…

SOLIDWORKS Composer反转关键帧实现产品安装过程

SOLIDWORKS Composer 是一款被用来制作交互式产品说明书的工具&#xff0c;可以帮助我们对产品设定精确的机构动画&#xff0c;并能根据材质生成一定细节的渲染图像。 今天我们主要向大家讲解的是&#xff0c;利用SOLIDWORKS Composer关键帧反转实现产品动态的安装。 一般情况下…

微信小程序通过 wxministore 实现类似于vuex的全局装填数据管理

首先 我们打开终端 引入依赖 npm install wxministore --save然后 如果你是新版开发者工具 就 npm i构建一下 如果你是 老版本的 微信开发者工具 就打开右上角详情 选择本地管理 勾选 使用 npm 模块 然后 在根目录下创建一个 store.js 当然建在哪是你自己决定的 反正 后面能…

密集人头检测数据集汇总和格式转换

1、VSCrowd 2022年9月新出的数据集,数据集链接:https://github.com/HopLee6/VSCrowd-Dataset 网盘地址:链接:https://pan.baidu.com/s/17VARxt59y7GnUHIskEGzKw?pwd=m9qo 提取码:m9qo 数据格式: FrameID HeadID x1 y1 x2 y2 p1 p2 HeadID x1 y1 x2 y2 p1 p2 … Fram…

长城网络靶场第三题

关卡描述&#xff1a;1.oa服务器的内网ip是多少&#xff1f; 先进行ip统计&#xff0c;开始逐渐查看前面几个ip 基本上都是b/s&#xff0c;所以大概率是http&#xff0c;过滤一下ip 第一个ip好像和oa没啥关系 第二个ip一点开就是 oa&#xff0c;应该就是他了。 关卡描述&a…