MQ相关介绍

news2024/11/14 17:44:52

14cdec0c38a440d6ac92e43114a134c2.jpg【1】MQ:MessageQueue,消息队列。 队列,是一种FIFO 先进先出的数据结构。消息由生产者发送到MQ进行排队,然后按原来的顺序交由消息的消费者进行处理。QQ和微信就是典型的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】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积压大量未消费消息。此种情况可以将这些消费不成功的消息转发到其它队列里去(类似死信队列),后面再慢慢分析死信队列里的消息处理问题。

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

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

相关文章

Seata学习

Seata Seata 是一款开源的分布式事务解决方案,致力于在微服务架构下提供高性能和简单易用的分布式事务服务。 官网地址:https://seata.io/zh-cn/index.html 为什么会产生分布式事务? 示例:用户下单后需要创建订单,同时…

关于动态内存管理中的常见练习题

文章目录 前言练习1:练习2:练习3:练习4: 前言 学习完C语言中的动态内存管理,大家开始利用动态内存管理来去开辟空间,经过一顿狂敲代码后,发现了问题,程序要么崩掉,要么运…

字符串的创建(直接赋值与new的区别)- 字符串常量池

文章目录 1.字符串 "hello" 与 new String("hello")的区别2.intern()的使用; 总结 本文开始 1.字符串 “hello” 与 new String(“hello”)的区别 字符串常量池:存储着创建的引用地址的引用 String s1 "hello"; String…

python 之 矩阵相关操作

文章目录 1. **创建矩阵**:2. **矩阵加法**:3. **矩阵乘法**:4. **矩阵转置**:5. **元素级操作**:6. **汇总统计**:7. **逻辑操作**: 理解你的需求,我将为每个功能写一个单独的代码块…

SPI学习笔记:DAC与ACD

一、SPI协议简介 SPI Serial Peripheral Interface,是串行外围设备接口,是一种高速,全双工,同步的通信总线。常规只占用四根线,节约了芯片管脚,PCB的布局省空间。现在越来越多的芯片集成了这种通信协议&a…

python【多线程、单线程、异步编程】三个版本--在爬虫中的应用

并发编程在爬虫中的应用 之前的课程,我们已经为大家介绍了 Python 中的多线程、多进程和异步编程,通过这三种手段,我们可以实现并发或并行编程,这一方面可以加速代码的执行,另一方面也可以带来更好的用户体验。爬虫程…

解读Stata输出的OLS回归结果

Stata是一个广泛用于统计分析和数据管理的软件,以下是一些Stata的基础命令: 输入数据:use + 数据文件路径 显示数据:browse 或 list 或 describe 选择数据:keep 或 drop 或 select 或 exclude 建立变量和赋值:generate 或 replace 汇总数据:summarize 或 tabulate 画图:…

自学SLAM(4)《第二讲:三维物体刚体运动》作业

前言 小编研究生的研究方向是视觉SLAM,目前在自学,本篇文章为初学高翔老师课的第二次作业。 文章目录 前言1.熟悉 Eigen 矩阵运算2.几何运算练习3.旋转的表达4.罗德里格斯公式的证明5.四元数运算性质的验证6.熟悉 C11 1.熟悉 Eigen 矩阵运算 设线性⽅程 …

cordens

1 coredns的用途 CoreDNS 是一个灵活可扩展的 DNS 服务器,可以作为 Kubernetes 集群 DNS,在Kubernetes1.12版本之后成为了默认的DNS服务。 与 Kubernetes 一样,CoreDNS 项目由 CNCF 托管。 coredns在K8S中的用途,主要是用作服务发现&#x…

企业知识库管理软件介绍,打造企业最强大脑!

企业知识经验既是企业稳定可控的基础,也是企业继续长足发展的基石,如何实现组织内外部知识沉淀,让知识在组织内外传播与应用,就成为我们广大企业负责人应该思考的问题了。 企业知识库管理 随着与人工智能技术的融合,知…

arcgis js api 4.x通过TileLayer类加载arcgis server10.2发布的切片服务跨域问题的解决办法

1.错误复现 2.解决办法 2.1去https://github.com/Esri/resource-proxy 网站下载代理配置文件,我下载的是最新的1.1.2版本,这里根据后台服务器配置情况不同有三种配置文件,此次我用到的是DotNet和Java. 2.2 DotNet配置 2.2.1 对proxy文件增加…

第 368 场 LeetCode 周赛题解

A 元素和最小的山形三元组 I 前后缀操作&#xff1a;求出前后缀上的最小值数组&#xff0c;然后枚举 j j j class Solution { public:int minimumSum(vector<int> &nums) {int n nums.size();vector<int> l(n), r(n);//l[i]min{nums[0],...,nums[i]}, r[i]mi…

AirPods Pro的降噪功能让你体验更好,那么如何打开这个功能

本文介绍了如何在AirPods Pro上使用降噪功能&#xff0c;如何关闭它&#xff0c;以及该功能的工作原理。 AirPods Pro和AirPods Max支持降噪。你的设备必须运行iOS 13.2或iPadOS 13.2或更高版本才能使用降噪。 如何在AirPods Pro上打开降噪功能 AirPods Pro凭借其噪音控制功…

leetCode 30.串联所有单词的子串

给定一个字符串 s 和一个字符串数组 words。 words 中所有字符串 长度相同。s 中的 串联子串 是指一个包含 words 中所有字符串以任意顺序排列连接起来的子串。 例如&#xff0c;如果 words ["ab","cd","ef"]&#xff0c; 那么 "abcdef&…

如何利用示波器解析I2C数据

前言 &#xff08;1&#xff09;如果有嵌入式企业需要招聘校园大使&#xff0c;湖南区域的日常实习&#xff0c;任何区域的暑假Linux驱动实习岗位&#xff0c;可C站直接私聊&#xff0c;或者邮件&#xff1a;zhangyixu02gmail.com&#xff0c;此消息至2025年1月1日前均有效 &am…

【5G PHY】5G SS/PBCH块介绍(一)

博主未授权任何人或组织机构转载博主任何原创文章&#xff0c;感谢各位对原创的支持&#xff01; 博主链接 本人就职于国际知名终端厂商&#xff0c;负责modem芯片研发。 在5G早期负责终端数据业务层、核心网相关的开发工作&#xff0c;目前牵头6G算力网络技术标准研究。 博客…

短视频矩阵打造攻略:玩转短视频

短视频矩阵系统是一个智能的短视频创作、发布、管理和分析的平台。该方法能够帮助用户迅速搭建起自身的短视频矩阵&#xff0c;并在多个平台上进行传播与展示&#xff0c;进而提升短视频的营销效率。该短视频矩阵系统具有如下基本功能&#xff1a; 1.短视频制作&#xff1a;为用…

队列的实现方式—Python数据结构(三)

队列 1. 定义 队列是一种常见的数据结构&#xff0c;用于按照先进先出&#xff08;FIFO&#xff09;的原则管理数据项。在Python中&#xff0c;有多种方法可以实现队列&#xff0c;其中最常见的包括使用列表&#xff08;list&#xff09;和使用标准库中的 queue 模块。队列通…

docker运行nginx镜像

今天在这里讲如何在docker上运行nignx镜像&#xff0c;并将配置文件和目录挂载到宿主机上&#xff0c;以实现方便统一的管理配置信息。 首先第一步需要拉取镜像&#xff0c;我们还是拉取最新的镜像&#xff0c;不需要添加tag版本号&#xff0c; docker pull nginx 拉取结束后用…

反射的作用( 越过泛型检查 和 可以使用反射保存所有对象的具体信息 )

1、绕过 编译阶段 为集合添加数据 反射是作用在运行时的技术&#xff0c;此时集合的泛型将不能产生约束了&#xff0c;此时是可以 为集合存入其他任意类型的元素的 。泛型只是在编译阶段可以约束集合只能操作某种数据类型&#xff0c;在 编译成Class文件进入 运行阶段 的时候&a…