别裁伪体亲风雅,转益多师是汝师。这篇文章主要讲述3万字聊聊什么是RocketMQ相关的知识,希望能为你提供帮助。
大家好,我是Leo。
这是开端的第三次循环了。当前正在正处于RocketMQ基础原理。
??4万字聊聊阿里二面,保证你看不完??
??聊聊Redis面试题??
??3万字聊聊什么是Redis(完结篇)??
??3万字聊聊什么是MySQL(初篇)??
??2万字聊聊什么是秒杀系统(中)??
为什么需要消息队列?一个大型的系统中,随着业务量,数据体量逐渐变的复杂。越来越多的模块耦合在一起,相互调用,只要有一块出问题,几乎都是致命的。
消息队列可以解决哪些场景?
异步处理电商系统的整个流程还是非常长的,如果所有流程都同步执行的话。肯定是保证不了那么高的并发的。所以可以借助 ??RocketMQ?
??只要风险管控,库存锁定之后,把当前订单信息写入到 ??RocketMQ?
?即可返回客户端。
写到客户端之后,订单服务,用户服务,通知服务等会根据 ??Topic+Tag?
? 进行消费。这步也就是 异步处理。可以提升并发量。
流量控制流量控制也就是安全问题,如何防止用户过多的请求压垮我们的秒杀系统。没加消息队列过滤的请求流程图是上述的。加了MQ过滤之后可以看如下图。
如果MQ堆积了大量的秒杀请求没有处理,说明当前的后端能力小于请求压力。这个时候后端不会宕机,他会按照自己的节奏尽快的处理完MQ的所有消息。当MQ有空闲的地方空出来之后,他又会继续接收请求。
对于超时的请求可以直接丢弃,APP 将超时无响应的请求处理为秒杀失败即可。运维人员 还可以随时增加秒杀服务的实例数量进行水平扩容,而不用对系统的其他部分做任何更改
如果没有MQ作为流量控制的话,所有的请求都打到后端,后端就会宕机。
这里还可以通过令牌桶的思路来达到相同的效果。而且令牌桶的实现更简单。
?这里MQ堆积下面会详细介绍。?
?令牌桶控制流量的原理是?:单位时间内只发放固定数量的令牌到令牌桶中,规定服务在处理 请求之前必须先从令牌桶中拿出一个令牌,如果令牌桶中没有令牌,则拒绝请求。这样就保 证单位时间内,能处理的请求不超过发放令牌的数量,起到了流量控制的作用
实现的方式也很简单,不需要破坏原有的调用链,只要网关在处理 APP 请求时增加一个获 取令牌的逻辑
令牌桶可以简单地用一个有固定容量的消息队列加一个“令牌发生器”来实现:令牌发生器 按照预估的处理能力,匀速生产令牌并放入令牌队列(如果队列满了则丢弃令牌),网关在 收到请求时去令牌队列消费一个令牌,获取到令牌则继续调用后端秒杀服务,如果获取不到 令牌则直接返回秒杀失败
服务解耦先看下面两张图。一个是单体结构,一个是微服务+MQ架构。能很清晰度看出来,第二张图简单一些。就是借助的是MQ的解耦特性。为后续的维护,新增新需求,新功能。都是非常优秀的。
不管系统怎么变,任何系统都没有联系,唯一有联系的就是MQ。 系统生产系统只发给MQ,系统消费消息也是只从MQ中消费。
MQ如何选择?常用的消息队列
优点
上个篇幅已经介绍了。
缺点
个人选型
我的技术选型是RocketMQ,主要原因如下
这里后续,经验丰富的时候会回来继续深入,技术选型。这里没那么简单!
主题和队列最初的消息队列就是我们平时简单使用的 ?
?Queue?
?,随着架构的演变,标准化跟不上演进速度,甚至到最后被废弃。
那么这个章节描述的主题和队列是什么?主题和队列又有什么关系?
队列模型
最初的队列模型就是 ?简单的先进先出(FNFO)?
业务变得越来越复杂之后,出现了多个生产者向一个消息队列里发送,然后又有多个消费者向一个消息队列里接收。这些消费者之间实际上是竞争的关系,每个消费者只能收到队列中的一部分消息,也就是说任何一条消息只能被其中的一个消费者收到。
如果需要将一份订单消息数据分发给多个消费者(用户服务,通知服务),要求每个消费者都能收到全量的消息,这个时候,单个队列就满足不了需求,一个可行的解决方式是,为每个消费者创建一个单独的队列,让生产者发送多份
显然这种方法是不可取的,违背了解耦的目的。而且每一份数据都会copy了好多份。极大的占用了内存。
为了解决这个问题,演化出了另外一种消息模型:?发布 - 订阅模型
在发布 - 订阅模型中,消息的发送方称为发布者(Publisher),消息的接收方称为订阅者 (Subscriber),服务端存放消息的容器称为主题(Topic)。发布者将消息发送到主题 中,订阅者在接收消息之前需要先“订阅主题”。“订阅”在这里既是一个动作,同时还可以认为是主题在消费时的一个逻辑副本,每份订阅中,订阅者都可以接收到主题的所有消息。
在这种发布 - 订阅模型中,如果只有一个订阅者,那它和队列模型就基本是一样 的了。也就是说,发布 - 订阅模型在功能层面上是可以兼容队列模型的。
RocketMQ消息模型
RocketMQ消息模型采用的是标准的发布-订阅模型,在 RocketMQ 的术语表中,生产者、消费者和主题与我在上面 讲的发布 - 订阅模型中的概念是完全一样的。
RocketMQ也有队列的概念,在RocketMQ中是非常重要的,我们可以先看看消费机制。
?消费机制:? 几乎所有的消息队列都使用一种,简便的?(请求,确认)?机制 。确保消息不会在传递过程中由于网络或服务器故障丢失。具体的做法也非常简单。
在生产端,生产者先将消息 发送给服务端,也就是 Broker,服务端在收到消息并将消息写入主题或者队列中后,会给生产者发送确认的响应。
如果生产者没有收到服务端的确认或者收到失败的响应,则会重新发送消息;在消费端,消费者在收到消息并完成自己的消费业务逻辑(比如,将数据保存到数据库中)后,也会给服务端发送消费成功的确认,服务端只有收到消费确认后,才认为一条消息被成功消费,否则它会给消费者重新发送这条消息,直到收到对应的消费成功确认
?如下图?
这套机制很好地保证了消息传递过程中的可靠性,但是,引入这个机制在消费端带来了一个很大的问题!
为了确保消息的有序性,在某一条消息被成功消费之前,下一条消息是不能被消费的,否则就会出现消息空洞,?违背了有序性这个原则?
也就是说,每个主题在任意时刻,至多只能有一个消费者实例在进行消费,那就没法通过水平扩展消费者的数量来提升消费端总体的消费性能。为了解决这个问题,RocketMQ 在主 题下面增加了队列的概念
每个主题包含多个队列,通过多个队列来实现多实例并行生产和消费。需要注意的是, RocketMQ 只在队列上保证消息的有序性,主题层面是无法保证消息的严格顺序的。
RocketMQ 中,订阅者的概念是通过消费组(Consumer Group)来体现的。每个消费组 都消费主题中一份完整的消息,不同消费组之间消费进度彼此不受影响,也就是说,一条消 息被 Consumer Group1 消费过,也会再给 Consumer Group2 消费。
消费组中包含多个消费者,同一个组内的消费者是竞争消费的关系,每个消费者负责消费组 内的一部分消息。如果一条消息被消费者 Consumer1 消费了,那同组的其他消费者就不 会再收到这条消息。
在 Topic 的消费过程中,由于消息需要被不同的组进行多次消费,所以消费完的消息并不 会立即被删除,这就需要 RocketMQ 为每个消费组在每个队列上维护一个消费位置 (Consumer Offset),这个位置之前的消息都被消费过,之后的消息都没有被消费过, 每成功消费一条消息,消费位置就加一。这个消费位置是非常重要的概念,我们在使用消息 队列的时候,丢消息的原因大多是由于消费位置处理不当导致的。
【3万字聊聊什么是RocketMQ】
推荐阅读
- WebRTC 服务器常见架构
- JVM | 第2部分(虚拟机执行子系统《深入理解 Java 虚拟机》 #yyds干货盘点#)
- 炒上天的NFT,元宇宙的隐形秩序之钥(他们为什么火)
- 前端新手快速上手APICloud App开发
- kali2021 linux安装后初始化配置
- 使用APICloud AVM框架开发人事档案管理助手app实战
- 线上k8s集群TTL 机制排毒,Job已经通过API 增加了Job的TTL 时长,且成功响应,为什么系统还是清理了Job()
- 关于Veeam CDP的几个概念
- OpenHarmony啃论文成长计划--分布式软总线关键技术普适计算初探