消息中间件之RocketMQ(三)

常见问题

1.重复消费

  • 产生的原因是发送消息时采用了多数分布式消息中间件产品提供的最少一次(at least once)的投递保障,对于这个问题最常见的解决方案,就是消息消费端实现业务幂等,只要保持幂等性,不管来多少条重复消息,最后处理的结果都是一样的
  • 保障策略有at most once 最多消费一次, at least once 最少消费一次, exactly once 刚好一次,RocketMQ不支持exactly once只有一次的模式,因为要在分布式系统下实现发送不重复并且消费不重复,将会产生非常大的开销,RocketMQ为了追求高性能并没有支持此特性
    其实该问题的本质时网络调用存在不确定性,即既不成功也不失败的第三种状态,所以才会产生消息重复的问题

2.为什么RocketMQ不用ZooKeeper而要自己实现一个NameServer来注册?

为什么要RocketMQ自己实现注册中心,而不是用Zookeeper,Nacos?

3.Consumer分组有什么用? Producer分组的作用?

  • Producer Group
  • 生产者组(ProducerGroup)是一类生产者地集合,这类生产者通常发送一类消息并且发送逻辑一致,所以将这些生产者分组在一起,从部署结构上看,生产者通过生产者组的名字来标识自己是一个集群
  • 事务消息回查机制,可以使用到,同一个生产者组的生产消息逻辑是相同的,所以当事务消息向Broker提交本地事务不成功时,有可能是在执行完本地事务之后宕机的,那么Broker只需要向同一个Producer Group中的任意一个Producer调用事务回查就可以获取到本地事务的执行结果
  • Consumer Group
  • 消费者组(ConsumerGroup)是一类消费者的组合,这类消费者通常消费同一类消息并且消费逻辑一致,所以将这些消费者分组在一起,消费者组于生产者组类似,都是将相同角色的消费者分组在一起并命名的。分组是一个很精妙的概念设计,RocketMQ正是通过这种分组机制,实现了天然的消息负载均衡。
    消费消息时,通过消费者组实现了将消息分发到多个消费者服务器实例,比如某个主题由9条消息,其中,一个消费者组由3个实例(3个进程或者3台机器),那么每个实例将均摊3条消息,也就意味着我们可以很方便地通过增加机器来实现水平扩容

4.哪些环节会有丢消息的可能

在这里插入图片描述
这4个环节都有丢消息的可能

5.RocketMQ消息零丢失方案

1.生产者使用事务消息机制保证消息零丢失

在这里插入图片描述

1.1.1.为什么要发送这个half消息?有什么用

这个Half消息时在订单系统进行下单操作前发送,并且对下游服务的消费者是不可见的。
那这个消息的作用更多的体现在确认RocketMQ的服务是否正常。相当于嗅探下RocketMQ
服务是否正常,并且通知RocketMQ,我马上就要发一个很重要的消息了,你做好准备

1.1.2.half消息如果写入失败了怎么办?

如果没有half消息这个流程,那我们通常是会在订单系统中先完成下单,再发送消息给MQ.
这时候写入消息到MQ如果失败就会非常尴尬了,而Half消息如果写入失败,我们就可以认为MQ的服务,是有问题的,这时就不能通知下游服务了,我们可以在下单时给订单一个状态标记,然后等待MQ服务,正常后再进行补偿操作,等MQ服务正常后重新下单通知下游服务

1.1.3.订单系统写数据库失败了怎么办?

这个问题我们同样比较下没有使用事务消息机制时会怎么办?如果没有使用事务消息,我们只能判断
下单失败,抛出了异常,那就不往MQ发消息了,这样至少保证不会对下游服务进行错误的通知。但是这样的话,如果过一段时间数据库恢复过来了,这个消息就无法再次发送了,当然也可以设计另外的补偿机制,例如将订单数据缓存起来,再启动一个线程定时尝试往数据库写。如果使用事务机制,就可以有一种更优雅的方案,如果下单时,写数据库失败了(可能是数据库崩了,需要等待
一段时间才能恢复),那我们可以另外找个地方把订单消息先缓存起来(Redis、文本或者其他方式),
然后给RocketMQ返回一个UNKNOWN状态,这样RocketMQ就会过一段时间来回查事务状态,我们就可以在回查事务状态时再尝试把订单数据写入数据库,如果数据库这时候已经恢复了,那就能完成正常的下单,再继续后面的业务。这样这个订单的消息就不会因为数据库临时崩了而丢失

1.1.4.Half消息写入成功后RocketMQ挂了怎么办?

在事务消息的处理机制中,未知状态的事务状态回查是由RocketMQ的Broker主动发起的,也就是如果出现了这种情况,那RocketMQ就不会回调到事务消息中回查事务状态的服务,这时,我们就可以将订单一直标记为"新下单"的状态。而等RocketMQ恢复后,只要存储的消息
没有丢失,RocketMQ就会再次继续状态回查的流程

1.1.5.下单成功后如何优雅地等待支付成功?
  • 数据库方案.
    在订单场景下,通常会要求下单完成后,客户在一定时间内,例如10分钟内完成订单支付,支付完成
    后才会通知下游服务进行进一步地营销补偿?
    如果不适用事务消息,那通常会怎么办?
    最简单地方式是启动一个定时任务,每隔一段时间扫描订单表,比对未支付的订单的下单时间,将超时的
    订单进行回收,这种方式显然有很大问题的,需要定时扫描很庞大的一个订单信息,这对系统是个不小
    的压力。

  • 延迟消息方案.
    更进一步的方案是什么呢?是不是就可以使用RocketMQ提供的延迟消息机制,往MQ发一个延迟一分钟的
    消息,消费到这个消息后去检查订单的支付状态,如果订单已经支付,就往下游发送下单的通知,而如果
    没有支付,就再发一个延迟1分钟的消息,最终在第是个消息时把订单回收,这个方案就不用对全部的订单
    表进行扫描,而只需要每次处理一个单独的订单消息

  • 事务消息方案.
    利用事务消息的状态回查机制来替代定时的任务。在下单时,给Broker返回一个UNKNOWN的位置状态。
    而在状态回查的方法中去查询订单的支付状态。这样整个业务逻辑就会简单很多。只需要配置RocketMQ的
    事务消息回查次数(默认15此)和事务回查间隔时间(messageDelayLevel)就可以更优雅的完成这个支付状态
    检查的需求

1.1.6.事务消息机制的作用

整体来说,在订单这个场景下,消息不丢失的问题实际上就还是转化成了下单这个业务与下游服务
的业务的分布式事务一致性问题,而事务一致性问题一直依赖都是一个非常复杂的问题。而RocketMQ
的事务消息机制,实际上只保证了整个事务消息的一半,他保证的是订单系统下单和发消息这两个事件
的事务一致性,而对下游服务的事务并没有保证,但是即便如此,也是分布式事务的一个很好的降级方案,
目前来看,也是业内最好的降级方案

2.RocketMQ配置同步刷盘+(Dledger)Broker主从架构保证MQ主从同步时不会丢消息
2.1.1.同步刷盘

可以简单的把RocketMQ的刷盘方式flushDiskType配置成同步刷盘就可以保证消息在刷盘过程中不会丢失了

2.1.2.Dledger的文件同步

在这里插入图片描述

  • 在使用Dledger技术搭建的RocketMQ集群中,Dledger会通过两阶段提交的方式抱着呢个文件在主从之间成功同步
  • 简单来说,数据同步会通过两个阶段,一个是uncommited阶段,一个是commiitted阶段Leader Broker上的Dledger收到一条消息后,会标记为uncommitted状态,然后他通过自己的DledgerServer组件把这个uncommitted数据发送给Follower Broker的DledgerServer组件。接着Follower Broker的DledgerServer收到uncommitted消息之后,必须返回一个ack给Leader Broker的Dledger,如果Leader Broker收到超过半数的Follower Broker返回的ack之后,
    就会把消息标记为committed状态,再接下来,Leader Broker上的DledgerServer就会发送committed消息给Follower Broker上的DledgerServer,让它们把消息也标记为committed状态,这样,就基于Raft协议完成了两阶段的数据同步
2.1.3.消费者端不要使用异步消费机制
  • 正常情况下,消费者端都是需要先处理本地事务,然后再给MQ一个ACK相应,这时MQ
    就会修改Offset,将消息标记为已消费,从而不再往其他消费者推送消息。所以在Broker的
    这种情况会造成服务端消息丢失,这种异步消费的方式,就有可能造成消息状态返回后消费者
    本地业务逻辑处理失败造成消息丢失的可能
2.1.4.RocketMQ特有的问题,NameServer挂了如何保证消息不丢失
  • NameServer在RocketMQ中,扮演一个路由中心的角色,提供到Broker的路由功能。
    但是其实这样的路由中心这样的功能,在所有的MQ中都是需要的,Kafka使用ZooKeeper
    和一个作为Controller的Broker一起来提供路由服务的,整个功能是相当复杂纠结的。而
    RabbitMQ是由每一个Broker来提供路由服务,只有RocketMQ把这个路由中心单独抽取了
    出来,并独立部署,每一个NameServer都是独立的,集群中任意多的节点挂掉,都不会影响
    它提供的路由功能,如果集群中所有的NameServer节点都挂了呢?
  • 有很多人就会认为生产者和消费者中都会有全部路由信息的缓存副本,那整个服务可以正常工作
    一段时间,当NameServer全部挂了后,胜场这和消费者是立即就无法工作了的
  • 回到消息不丢失的问题。在这种情况下,RocketMQ相当于整个服务都不可用了,那它本身肯定无法给我们
    保证消息不丢失了。我们只能自己设计一个降级方案来处理这个问题了。例如再订单系统中,如果多次尝试
    发送RocketMQ不成功,那就只能另找地方(Redis、文件或者内存等)把订单消息缓存下来,然后起一个线程
    定时地扫描这些失败地订单消息,尝试往RocketMQ发送,这样等RocketMQ的服务恢复过来后,就能第一
    时间把这些消息重新发送出去。整个这套降级的机制,在大型互联网项目中,都是必须要有的
2.1.5.RocketMQ消息零丢失方案总结
  • 1.生产者使用事务消息机制
  • 2.Broker配置同步刷盘+Dledger主从架构
  • 3.消费者不要使用异步消费
  • 4.整个MQ挂了之后准备降级方案
  • 这套方案在各个环节都大量地降低了系统地处理性能以及吞吐量。在很多场景下,这套方案带来的性能损失
    的代价可能远大于部分消息丢失的代价。所以在使用这套方案时,要根据实际的业务情况来考虑,
    例如,如果针对所有服务器都在同一个机房的场景,完全可以把Broker配置成异步刷盘来提升吞吐量。
    而在有些对消息可靠性要求没有那么高的场景,在生产者端就可以采用其他一些更简单的方案来提升吞吐,
    而采用定时对账、补偿的机制来提高消息的可靠性。而如果消费者不需要进行消息存盘,
    那使用异步消费的机制带来的性能提升也是非常显著的。

3.使用RocketMQ如何保证消息顺序

3.1.为什么要保证消息有序?

比如,下单完之后,需要支付成功,才会进行物流快递,不能先让物流服务执行,再支付成功

3.2.如何保证消息有序?
  • 全局有序。整个MQ系统的所有消息岩哥按照队列先入先出顺序进行消费
  • 局部有序。只保证一部分关键消息的消费顺序
  • 首先我们需要分析下这个问题,在通常的业务场景中,全局有序和局部有序哪个更重要?其实在大部分的MQ业务场景,我们只需要保证局部有序就可以了,对于电商订单场景,只要保证一个订单的所有消息是有序的就可以了,全局消息的顺序并不会太关心
  • 落地到RocketMQ。通常情况下,发送者发送消息时,会通过MessageQueue轮询的方式
    保证消息尽量均匀地分布到所有的MessageQueue上,而消费者也就同样需要从多个MessageQueue
    上消费消息。而MessageQueue是RocketMQ存储消息的最小单元,它们之间的消息都是互相隔离的,
    在这种情况下,是无法保证消息全局有序的,而对于局部有序的要求,只需要将有序的一组消息都存入
    同一个MessageQueue里,这样MessageQueue的FIFO设计天生就可以保证这一组消息的有序。
    RocketMQ中,剋在发送者发送消息时指定一个MessageSelector对象,让这个对象来决定消息发到
    哪一个MessageQueue。这样就可以保证一组有序的消息能够发到同一个MessageQueue里。
  • 另外,通常所谓的保证Topic全局消息有序的方式,就是将Topic配置成只有一个MessageQueue队列(默认是4个)。这样天生就能保证消息全局有序,这种方式对整个Topic的消息吞吐影响是非常大的,如果这样用,基本上就没有用MQ的必要了

4.使用RocketMQ如何快速处理积压消息

4.1.1.如何确定RocketMQ有大量的消息积压?
  • 在正常情况下,使用MQ都会要尽量保证它的消息生产速度和消费速度整体上是平衡的,但是如果部分消费者系统出现故障,就会造成大量的消息积累。这类问题通常在实际工作中会出现得比较隐蔽。例如某一天一个数据库突然挂了,大家大概率就会集中处理数据库得问题,等好不容易把数据库恢复过来了,这时基于这个数据库服务得消费者程序就会积累大量的消息。或者网络波动等情况,也会导致消息大量的积累。这在一些大型的互联网项目中,消息积压的速度是相当恐怖的,所以消息积压是个需要时时关注的问题

  • 对于消息积压,如果是RocketMQ或者Kafka还好,它们的消息积压不会对性能造成
    很大的影响,而如果是RabbitMQ的话,那就不太好了,大量的消息积压可以瞬间造成
    性能直线下滑。对于RocketMQ来说,有个最简单的方式来确定消息是否有积压。那就是使用web控制台,就能直接看到消息的积压情况,另外也可以通过mqadmin指令在后台检查各个Topic的消息延迟情况,还可以在它的${sotrePathRootDir}/config目录下落地一系列
    的json文件,也可以用来跟踪消息积压情况

4.1.2.如何处理大量积压的消息
  • 如果Topic下的MessageQueue配置得是足够多的,那每个Consumer实际上会分配
    多个MessageQueue来进行消费。这个时候,就可以简单地通过增加Consumer的服务节点数量来加快消息的消费,等积压消息消费完了,再恢复成正常情况。最极限的情况是把Consumer的节点个数设置成MessageQueue的个数相同。但是如果此时再继续增加Consumer的服务节点就没有用了
  • 如果Topic下的MessageQueue配置不够多的话,那就不能用上面这种增加Consumer节点个数的方法了
    这时如果要快速处理积压的消息,可以创建一个新的Topic,配置足够的多MessageQueue.然后把所有
    消费者节点的目标Topic转向新的Topic,并紧急上线一组新的消费者,只负责消费旧Topic中的消息,
    并转储到新的Topic中,这个速度是可以很快的,然后在新的Topic上,就可以通过增加消费者个数来提高
    消费速度了.之后再根据情况恢复成正常的情况

5.RocketMQ的消息轨迹

RocketMQ默认提供了消息轨迹的功能,这个功能在排查问题时是非常有用的

5.1.RocketMQ消息轨迹数据的关键属性
5.1.1 Producer
  • 生产实例信息
  • 发送消息时间
  • 消息是否发送成功
  • 发送耗时
5.1.2 Consumer
  • 消费实例信息
  • 投递时间,投递轮次
  • 消息是否消费成功
  • 消费耗时
5.1.3 Broker
  • 消息的Topic
  • 消息存储位置
  • 消息的Key值
  • 消息的Tag值
5.2.消息轨迹配置

broker.conf打开一个关键配置
traceTopicEnable=true,默认是false,关闭的

5.3 消息轨迹数据存储

默认情况下,消息轨迹数据是存于一个系统级别的Topic
RMQ_SYS_TRACE_TOPIC,这个Topic在Broker节点启动时
会自动创建出来,当然也可以自定义

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

视频监控方案设计:EasyCVR视频智能监管系统方案技术特点与应用

随着科技的发展,视频监控平台在各个领域的应用越来越广泛。然而,当前的视频监控平台仍存在一些问题,如视频质量不高、监控范围有限、智能化程度不够等。这些问题不仅影响了监控效果,也制约了视频监控平台的发展。 为了解决这些问…

【LMDeploy 大模型量化部署实践】学习笔记

参考学习教程【LMDeploy 的量化和部署】 理论 作业 使用 LMDeploy 以本地对话、网页Gradio、API服务中的一种方式部署 InternLM-Chat-7B 模型,生成 300 字的小故事 本地对话 API服务 Client 命令 端口转发 网页Gradio

C语言每日一题(48)回文链表

力扣 234 回文链表 题目描述 给你一个单链表的头节点 head ,请你判断该链表是否为回文链表。如果是,返回 true ;否则,返回 false 。 示例 1: 输入:head [1,2,2,1] 输出:true示例 2&#xff1…

【渗透测试】借助PDF进行XSS漏洞攻击

简介 在平时工作渗透测试一个系统时,常常会遇到文件上传功能点,其中大部分会有白名单或者黑名单机制,很难一句话木马上传成功,而PDF则是被忽略的一个点,可以让测试报告更丰富一些。 含有XSS的PDF制作步骤 1. 编辑器…

JavaSE基础学习

一、编程入门 二、Java语言概述 三、Java基本语法 四、程序流程控制 五、数组 六、面向对象(上) 数组工具类的封装: 七、面向对象(中) 八、面向对象(下) 九、异常处理 十、多线程 十一、常用类 十二、枚举类与注解 十三、集合 十四、泛型 十五、IO流 十六、网络编程 十七、反射…

Linux-----Shell编程之循环语句

一、小命令 1、echo echo -n 表示不换行输出 echo -e 表示输出转义符 常用的转义符 选项作用\r光标移至行首,并且不换行\s当前shell的名称,如bash\t插入Tab键,制表符\n输出换行\f换行,但光标仍停留在原处\表示插入"\&qu…

Idea上操作Git回退本地版本,怎么样保留已修改的文件,回退本地版本的四种方式代表什么?

Git的基本概念:Git是一个版本控制系统,用于管理代码的变更历史记录。核心概念包括仓库、分支、提交和合并。 1、可以帮助开发者合并开发的代码 2、如果出现冲突代码的合并,会提示后提交合并代码的开发者,让其解决冲突 3、代码文件版本管理 问题描述 当我们使用git提交代码…

unity 装饰器模式(实例详解)

文章目录 简介1. **组件装饰器(Component Decorators)**:2. **游戏对象特效装饰器(GameObject Effects Decorator)**:3. **输入处理装饰器(Input Handling Decorators)**:4. **性能优化装饰器(P…

2022年至2023年广东省职业院校技能大赛高职组“信息安全管理与评估”赛项样题

2022 年至 2023 年广东省职业院校技能大赛高职组“信息安全管理与评估”赛项样题 一、 第一阶段竞赛项目试题 本文件为信息安全管理与评估项目竞赛第一阶段试题,第一阶段内容包 括:网络平台搭建、网络安全设备配置与防护。 本阶段比赛时间为 180 分钟…

Make.com的发送邮件功能已经登峰造极

make.com的发送邮件功能已经做到了登峰造极。 我给你个任务,让你发送个新邮件给谁谁,你一定想到SMTP服务器不就行了。 我给你第二个任务,我让你自动回复一个邮件,注意是回复。 做不到了吧~~!…

[C#]winform部署yolov7+CRNN实现车牌颜色识别车牌号检测识别

【官方框架地址】 https://github.com/WongKinYiu/yolov7.git 【框架介绍】 Yolov7是一种目标检测算法,全称You Only Look Once version 7。它是继Yolov3和Yolov4之后的又一重要成果,是目标检测领域的一个重要里程碑。 Yolov7在算法结构上继承了其前…

C++ 设计模式之责任链模式

【声明】本题目来源于卡码网(卡码网KamaCoder) 【提示:如果不想看文字介绍,可以直接跳转到C编码部分】 【设计模式大纲】 【简介】 --什么是责任链模式(第21种设计模式) 责任链模式是⼀种行为型设计模式&am…

计算机工作原理解析和解剖(基础版)

我们会从软件⼯程师的⻆度解释计算机是如何⼯作的,我们的主要⽬标既不是期待 ⼤家可以造出⾃⼰的计算机,也不是介绍如何编程,⽽是希望让⼤家了解计算机的核⼼⼯作机制后,打破计算机的神秘感,并且有利于理解我们平时编程…

心理学大纲

简介 psychology,“psyche”(ψυχή):意为"soul"(灵魂),即对我们灵魂的研究 我的学习的目的 了解人精神世界的模型,人格的形成],作为观察分析他人内心的理论指导,便于我实践了解情绪的机理,…

vite项目创建

1.使用命令创建一个vite项目 npm init vuelatest vite.config.js配置 import { fileURLToPath, URL } from "node:url";import { defineConfig, loadEnv } from "vite"; import vue from "vitejs/plugin-vue"; export default defineConfig(({…

ZK监控方法以及核心指标

文章目录 1. 监控指标采集1.1 zk版本高于3.6.0监控指标采集1.2 zk版本低于3.6.0监控指标采集1.3 配置promethues采集和大盘 2. 核心告警指标3. 参考文章 探讨zk的监控数据采集方式以及需要关注的核心指标,便于日常生产进行监控和巡检。 1. 监控指标采集 3.6.0 版本…

哪吒汽车与经纬恒润合作升级,中央域控+区域域控将于2024年落地

近日,在2024哪吒汽车价值链大会上,哪吒汽车与经纬恒润联合宣布合作升级,就中央域控制器和区域域控制器展开合作,合作成果将在山海平台新一代车型上发布。 哪吒汽车首席技术官戴大力、经纬恒润副总裁李伟 经纬恒润在智能驾驶领域拥…

Java入门高频考查基础知识6-深入挖掘Java集合框架的奇幻世界(45题3.6万字参考答案)

在Java编程语言中,集合(Collection)指的是存储一组对象的容器。Java提供了一套丰富的集合框架,以及包含在Java标准库中的集合类。这些集合类提供了各种功能和操作,可以方便地对一组对象进行管理和操作。 目录 一、集合…

VUE引入DataV报错记录

DataV官网(不支持Vue3):Welcome | DataV 一、按照官网引入后报错 【1】 Failed to resolve entry for package "dataview/datav-vue3". The package may have incorrect main/module/exports specified in its package.json. 将…

在docker中配置 Linux ls 配色方案 与 shell 提示符

发行版中默认的配置一般非常合理,但是docker中往往忽略了这些简单的配置,备忘一下 1. ls 配色方案 vim ~/.bashrc 在文件最末尾加入如下一行内容: export LS_COLORS"rs0:di01;34:ln01;36:mh00:pi40;33:so01;35:do01;35:bd40…