消息中间件之RocketMQ(五)

RocketMQ高性能背后的核心原理

1.消息主从复制

如果Broker以一个集群的方式部署,会有一个master节点和多个Slave节点,消息需要从master复制到slave上,而消息复制的方式分为同步复制和异步复制。
同步复制:
同步复制是等Master和Slave都写入消息成功后才反馈给客户端写入成功的状态.在同步复制下,如果Master节点故障,Slave上有全部的数据备份,这样容易恢复数据,但是同步复制会增大数据写入的延迟,降低系统的吞吐量

异步复制:
只要Master写入消息成功,就反馈给客户端写入成功的状态,然后再异步地将消息复制给Slave节点。在异步复制下,系统拥有较低地延迟和较高地吞吐量,但是如果master节点故障,而有些数据没有完成复制,就会造成数据丢失

配置方式:
消息复制方式是通过Broker配置文件里地brokerRole参数进行设置的,这个参数可以被设置成ASYNC_MASTER,SYNC_MASTER,SLAVE三个值中的一个

2.负载均衡–重点

Producer
在这里插入图片描述
Prodicer发送消息时,默认会轮询目标Topic下的所有MessageQueue,并采用递增取模的方式往不同的MessageQueue上发送消息,已达到让消息平均落在不同的queue上的目的,而由于MessageQueue是分布在不同的Broker上的,所以消息也会发送到不同的Broker上,见上图,同时生产者在发送消息时,可以指定一个MessageQueueSelector,通过这个对象来将消息发送到自己指定的MessageQueue上,这样可以保证消息局部有序

Consumer
Consumer也是以MessageQueue为单位来进行负载均衡的,分为集群模式和广播模式

集群模式
在集群消费模式下,每条消息只需要投递到订阅的这个Topic的Consumer Group下的
一个实例即可,RocketMQ采用主动拉取的方式拉取并消费消息,在拉取的时候需要
明确指定拉取哪一条MessageQueue,没当实例的数量有变更,都会触发一次所有实例的负载均衡,这时候会按照queue的数量和实例的数量平均分配queue给每个实例。每次分配时,都会将MessageQueue和消费者ID进行排序后,再用不同的分配算法进行分配,内置的分配的算法共有六种,分别对应AllocateMessageQueueStrategy下的六种实现类,可以在consumer中直接set来指定,默认情况下使用的时最简单的平均分配策略

  • AllocateMachineRoomNearby
    将统计放的Consumer和Broker有限分配在一起。这个策略可以通过一个matchineRoomResolve对象来定制Consumer和Broker的机房解析规则。然后还需要引入另外一个分配策略来对统计放的Broker和Consumer进行分配一般也就用简单的平均分配策略或者轮询分配策略(但是比较鸡肋,直接给属性指定机房更好)

  • AllocateMessageQueueAveragely
    平均分配,将所有MessageQueue平均分给每一个消费者
    在这里插入图片描述

  • AllocateMessageQueueAveragelyByCircle
    轮询分配。轮流地给一个消费者分配一个MessageQueue

  • AllocateMessageQueueByConfig
    不分配,直接指定一个MessageQueue,类似于广播模式,直接指定所有队列

  • AllocateMessageQueueByMachineRoom
    按逻辑机房地概念进行分配。又是对BrokerName和COnsumerId定制化地配置

  • ALlocateMessageQueueConsistenHash
    这个一致性哈希策略只需要指定一个虚拟节点数,使用一个Hash环地算法,
    虚拟节点是为了让Hash数据在环上分布更为均匀

广播模式
官博模式下,每一条消息都会投递给订阅了Topic的所有消费者实例,所以也就没有消息分配这一说,而在实现上,即使在Consumer分配Queue时,所有Consumer都分到所有的Queue.广播模式实现的关键是将消费者的消费偏移量不再保存到Broker当中

3.消息重试

首先对于广播模式下的消息,是不存在消息重试的机制的,即消息消费失败后,会再重新进行发送,而只是继续消费新的消息,而对于普通的消息,当消费者消费失败后,可以通过设置返回状态达到消息重试的结果

如何让消息进行重试?
集群消费方式下,消息消费失败后期望消息重试,需要在消息监听器接口的实现中明确进行配置。
可以有三种配置方式:
1.返回Action.ReconsumeLater (推荐)
2.返回null
3.抛出异常
如果希望消费失败后不重试,可以直接返回.CommitMessage

在这里插入图片描述
重试消息如何处理?
重试的消息会进入一个"%RETRY" + ConsumerGroup的队列中,然后RocketMQ默认允许每条消息最多重试16次,每重试间隔时间如图,随着重试次数的递增,重发间隔时间也是递增的,注:消费者实例要避免只有一个,否则重试次数是没有意义的

重试次数
如果消息重试16次后仍然失败,消息将不再投递,转为进入死信队列。另外一条消息无论重试多少次,这些重试消息的MessageId始终都是一样的。这个重试次数,RocketMQ可以进行定制,例如通过consumer.setMaxReconsumeTimes(20)// 将重试次数设置为20次,当定制的重试次数超过16次后,消息的重试时间间隔均为2小时

MessageId
在老版本的RocketMQ中,一条消息无论重试多少次,这些重试消息的MessgeId始终都是一样的但是在4.9.1版本中,每次重试MessageId都会重建

配置覆盖
消息最大重试次数的设置对相同GroupID下的所有Consumer实例有效,并且最后启动的Consuemr会覆盖之前启动的Consumer配置

4.死信队列

当一条消息消费失败,RocketMQ就会自动进行消息重试,而如果消息超过最大重试次数,RocketMQ就会认为这个消息有问题,但是此时,RocketMQ不会立刻将这个有问题的消息丢弃,而会将其发送到这个消费者组对应的一种特殊队列:死信队列
死信队列的名称是"%DLQ%+ConsumerGroup"

死信队列的特征:
1.一个死信队列对应一个ConsumerGroup,而不是对应某个消费者实例
2.如果一个ConsumerGroup没有产生死信队列,RocketMQ就不会为其创建相应的队列
3.一个死信队列中的消息不会再被消费者正常消费
4.死信队列的有效期跟正常消息相同,默认3天,对应broker.conf中的fileReservedTime属性,超过这个最长时间的消息都会被删除,而不管消息是否被消费过,通常,一条消息进入了死信队列,意味着消息再消费处理的过程中出现了比较严重的错误,并且无法自行恢复,此时,一般需要人工去查看死信队列中的消息,对错误原因进行排查,然后对死信消息进行处理,比如转发到正常的Topic重新进行消费或者丢弃

注:默认创建出来的死信队列,它里面的消息是无法读取的,在控制台和消费者中都无法读取,这是因为这些默认的死信队列,它们的权限perm被设置成了2:禁读(4,禁写,6:可读可写)需要手动将死信队列的权限配置改成6,才能被消费

5.消息幂等

幂等概念
在MQ系统中,对于消息幂等有三种实现语义
1.at most once 最多一次:每条消息最多只会被消费一次
2.at least once 至少一次:每条消息至少会被消费一次
3.exactly once 刚刚好一次:每条消息都追确定地消费一次

这三种语义都有它使用的业务场景。其中,at most once是最好保证的,
RocketMQ中可以直接使用异步发送,sendOneWay等方式就可以保证,
而at least once这个语义,RocketMQ也有同步发送、事务消息等很多方式能够保证,
而这个exactly once是MQ种最理想也是最难保证的一种语义,需要有非常惊喜的设计才行,RocketMQ只能保证at least once,保证不了exactly once,所以,使用RocketMQ时,需要由业务系统自行保证消息的幂等性,但是,对于Exactly once语义,阿里云上的商业版RocketMQ是有明确支持的,实现方式未开源

消息幂等的必要性。
在互联网应用种,由器在网络不稳定的情况下,消息队列RocketMQ的消息有可能会出现重复,这个重复简单可以概括为以下情况:

1.发送时消息重复
当一条消息已被成功发送到服务端并完成持久化,此时出现了网络闪断或者客户端宕机,导致服务端对客户端应答失败。如果此时生产者意识到消息发送失败并尝试再次发送消息,消费者后续会收到两条内容相同并且MessageId也相同的消息

2.投递时消息重复。
消息消费的场景下,消息已投递到消费者并完成业务处理,当客户端给服务端反馈应答的时候网络闪断,为了保证消息至少被消费一次,消息队列RocketMQ的服务端将在网络恢复后再次投递之前已被处理过的消息,消费者后续会受到两条内容相同并且MessageId也相同的消息

3.负载均衡时消息重复(包括但不限于网络抖动、Broker重启亿级订阅应用重启)
当RocketMQ的Broker或客户端重启,扩容,缩容时,会触发Rebalance,此时消费
者可能会受到重复消息

处理方式
在RocketMQ是无法保证每个消息制备投递一次,所以要在业务上自行来保证消息消费的幂等性。而要处理这个问题,RocketMQ的每条消息都有一个唯一的MessageId,这个参数在多次投递的过程种是不会改变的,所以业务上可以用这个MessageId来作为判断幂等的关键依据。但是,这个MessageId是无法保证全局唯一的,也会有冲突的情况,所以在一些对幂等要求严格的场景,最好是使用业务上唯一的标识比较靠谱,例如订单id,而这个业务标识可以使用Message的key来进行传递

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

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

相关文章

为什么网页打开慢?是服务器的问题吗?

当我们遇到网页加载缓慢时,首先想到的可能是服务器的问题。的确,服务器是影响网页加载速度的一个重要因素。然而,这并非是唯一的原因。实际上,网页加载速度受多种因素影响,包括但不限于服务器、网络带宽、DNS解析时间、…

linux0.11源码看信号的处理流程

序 日常Linux写代码或者使用中难免会使用siganl,包括我们使用ctrl-c结束程序,使用kill命令发送信号,或者说程序core后操作系统向程序发送的信号,以及我们程序内部自定义的信号处理。 我们选择linux0.11一个原因是它比较简单&…

程序员如何应对中年危机

中年危机是一个普遍存在的问题,不仅仅局限于程序员这个职业。不过,对于程序员来说,由于技术更新迅速,中年危机可能更加明显。以下是一些应对中年危机的建议: 持续学习新技术和工具:计算机技术发展迅速&…

快快销shop积分商城:全额积分抵扣营销 打造积分换购专区

快快销shop积分商城是一个创新的营销平台,它通过全额积分抵扣的策略,鼓励用户在商城内消费并积累积分。这种营销方式不仅能提升用户的购物体验,还能有效地促进销售。 全额积分抵扣意味着用户在商城内消费时,可以全额使用积分进行…

原生js是怎么创建元素的?

问: <div class"share-img"> <img src"../img/pic_share-tip.png" alt""> </div>原生js怎么创建一个这个元素? 回答: 问: 上面代码执行结果是什么样的? 回答:

攻防演练 |解决Nmap无法扫描B段资产问题

前段时间老大发来任务&#xff0c;让帮忙用nmap扫一些ip段&#xff0c;我拿过来就准备开扫… 但是发现nmap无法直接扫描同一B段不同C段下的IP段&#xff0c;例如111.111.111.0-111.111.222.255 原本我是准备写个工具联动nmap来扫描大批量IP段资产的 但是由于环境有些问题&am…

什么工具能将视频转成gif?分享一个在线制作gif网站

Gif动图看起来效果非常的炫酷&#xff0c;也很复杂。这种gif动图制作起来是不是也很麻烦呢&#xff1f;其实制作gif动画的方法非常的简单&#xff0c;不用下载软件&#xff0c;小白也能操作。只需要使用在线制作gif&#xff08;https://www.gif.cn/&#xff09;工具-GIF中文网&…

【云驻共创】零门槛Serverless课堂 应用全托管 so easy!

前言 一切要从一个风和日丽的早上说起&#xff1a; 那天&#xff0c;阳光正好&#xff0c;微风不燥。还来不及从容吃口早饭&#xff0c;我就接到了线上报警&#xff0c;赶忙打开了电脑&#xff0c;处理突发的流量高峰导致的页面报错。 重启好服务&#xff0c;饭都冷了。 我…

3dmax效果图渲染出现曝光怎么解决?

在使用3ds Max完成效果图渲染工作时&#xff0c;有时会遇到曝光过度的问题&#xff0c;这会使得渲染的图像出现光斑或者过亮&#xff0c;损害了效果的真实感和美观度。那么解决解决3dmax曝光问题呢&#xff1f;一起看看吧&#xff01; 3dmax效果图渲染出现曝光解决方法 1、相机…

使用Opencv-python库读取图像、本地视频和摄像头实时数据

使用Opencv-python库读取图像、本地视频和摄像头实时数据 Python中使用OpenCV读取图像、本地视频和摄像头数据很简单&#xff0c; 首先需要安装Python&#xff0c;然后安装Opencv-python库 pip install opencv-python然后在PyCharm或者VScode等IDE中输入对应的Python代码 一…

web前端---------盒子模型

1.内容 盒子的内容可以包含文字、图片等多种类型。 浏览器在加载网页时&#xff0c;会将元素按照内容区分为替换元素与非替换元素。 &#xff08;1&#xff09;替换元素指的是HTML中的一些形如<img>、<input>等非文本元素。 这些元素本身不包含任何内容&#x…

Spring Cloud 之Config详解

大家好&#xff0c;我是升仔 在微服务架构中&#xff0c;统一的配置管理是维护大规模分布式系统的关键。Spring Cloud Config为微服务提供集中化的外部配置支持&#xff0c;它可以与各种源代码管理系统集成&#xff0c;如Git、SVN等。本文将详细介绍如何搭建配置服务器、管理客…

司铭宇老师:汽车销售培训:汽车销售员培训:汽车销售技巧培训:汽车销售技巧和话术

汽车销售培训&#xff1a;汽车销售员培训&#xff1a;汽车销售技巧培训&#xff1a;汽车销售技巧和话术 汽车销售是一项充满挑战性的工作&#xff0c;它需要销售人员具备良好的沟通技巧、谈判技巧以及产品讲解能力。在这篇文章中&#xff0c;我们将详细探讨汽车销售中的技巧和话…

【MQ02】基础简单消息队列应用

基础简单消息队列应用 在上一课中&#xff0c;我们已经学习到了什么是消息队列&#xff0c;有哪些消息队列&#xff0c;以及我们会用到哪个消息队列。今天&#xff0c;就直接进入主题&#xff0c;学习第一种&#xff0c;最简单&#xff0c;但也是最常用&#xff0c;最好用的消息…

Nginx安装以及具体应用

文章目录 Centos7安装NginxNginx命令Nginx具体应用反向代理 location指令说明负载均衡动静分离 Nginx.conf配置详解 Centos7安装Nginx 下载地址&#xff1a;nginx: download 中间这个就是tar.gz包 Centos7安装Nginx 下载nginx-1.16.1.tar.gz上传到Centos7中的/user/local目…

漏洞攻击中怎么去做最全面覆盖的sql注入漏洞攻击?表信息是如何泄露的?预编译就一定安全?最受欢迎的十款SQL注入工具配置及使用

漏洞攻击中怎么去做最全面覆盖的sql注入漏洞攻击?表信息是如何泄露的?预编译就一定安全?最受欢迎的十款SQL注入工具配置及使用。 SQL注入是因为后台SQL语句拼接了用户的输入,而且Web应用程序对用户输入数据的合法性没有判断和过滤,前端传入后端的参数是攻击者可控的,攻击…

一位网友开始设计一个叫 VisionPro 的VR现实交互操作系统,可以将电脑屏幕的图片拖拽到现实空间摆放

在 Figma 中创建的资源和组件可以在 ShapesXR 中导入和同步&#xff0c;这样您就可以在 Mixedreality 中开始设计&#xff0c;而无需任何 3d 专业技能 Figma是一个矢量图形编辑器和原型设计工具&#xff0c;主要基于网页进行工作&#xff0c;通过macOS或Windows的桌面应用程序…

Docker命令---搜索镜像

介绍 使用docker命令搜索镜像。 命令 docker search 镜像命令:版本号示例 以搜索ElasticSearch镜像为例 docker search ElasticSearch

Redis的应用问题

目录 一、缓存穿透 问题描述 解决方案 缓存击穿 问题描述 解决方案 缓存雪崩 问题描述 解决方案 二、分布式锁 问题描述 解/决方案&#xff1a;使用redis实现分布式锁 优化之设置锁的过期时间 优化之UUID防误删 LUA脚本保证删除的原子性 LUA脚本 LUA脚本在Red…

Dockerfile入门指南:轻松创建定制化Docker镜像

镜像的定制实际上就是定制每一层所添加的配置、文件。如果我们可以把每一层修改、安装、构建、操作的命令都写入一个脚本&#xff0c;用这个脚本来构建、定制镜像&#xff0c;那么无法重复的问题、镜像构建透明性的问题、体积的问题就都会解决。这个脚本就是 Dockerfile。 Doc…