RocketMq

有道云笔记同步1

MQ:是一种提供消息队列服务的中间件,是一套提供了消息生产、存储、消费全过程的API的软件系统
MQ的用途 :
限流削峰:
超量请求会对其暂存其中
异步解耦:
使用MQ 实现异步
数据收集:
批量采集业务日志、监控数据、用户行为。
MQ的缺点:
1、系统可用性降低
2、系统复杂复杂度提高
3、如何保证消息的一致性

MQ常见协议
JMS:面向消息的中间件 PO/OO/AO的技术规范,他便与消息系统中的java应用程序进行消息交换,并且通过标准的产生、发送、接受消息的接口
STOMP:简单文本协议。是一个可互操作的连接格式,允许客户端与任何STOMP消息代理进行交互
AMQP:高级消息队列协议。提供统一消息服务的应用层标准,是应用协议的一个开发标准,是一种MOM设计。基于此协议的客户端与消息件可传递消息,并不受客户端、中间件不同产品,不同开发语言等条件的限制。
MQTT:消息队列遥测传输,即使通讯协议,是一种二进制协议。主要用于服务器和物联网设备的通信。该协议支持所有平台

概念:
基本概念(Message Model):RocketMQ主要有Producer、Broker、Consumer三部分组成,其中Producer负责生产消息,Consumer负责消费消息,Broker负责存储消息。Broker在实际部署过程中对应一台服务器,每个Broker可以存储多个Topic的消息,每个Topic的消息也可以分片存储与不同的Broker。Message Queue用于存储消息的物理地址,每个Topic中的消息地址存储于多个Message Queue中。ConsumerGroup由多个Consumer实例构成。
消息生产者(Producer):负责生产消息,一般由业务系统负责生产消息。一个消息生产者会吧业务应用系统里产生的消息发送到broker服务器。
RocketMQ提供多种发送方式:
1、同步发送(需要Broker返回确认信息)
2、异步发送(需要Broker返回确认信息)
3、顺序发送
4、单向发送
消息消费者(Consumer):负责消费消息,一般是后台系统负责异步消费。一个消息消费者会从Broker服务器拉取消息、并将其提供给应用程序。从用户应用的角度而言提供了两种消费形式:
1、拉取式消费:Consumer主动从Broker中拉去消息,主动权由Consumer控制。一旦获取了批量消息,就会启动消息过程。不过,该方式的实时性较弱,即Broker中有了新的消息时消费者并不能及时发现并消费。
2、推动式消费:该模式下的Broker收到数据后会主动推送给Consumer。该获取方式一般实时性较高。该获取方式是典型的发布-订阅模式,即Consumer向其关联的Queue注册了监听器,一旦发现有新的消息到来就出发回调的执行,回调方法是Consumer是Queue中拉去消息。而这些都是基于Consumer与Broker间的长连接的。长连接的维护是需要消耗系统资源的。

队列:
一个Topic的Queue中的消息只能被一个消费者组中的一个消费者消费。一个Queue中的消息不允许同一个消费者组中的多个消费者同时消费。
分片:分片指的是存放相应Topic的Broker。每个分片中会创建出相应数量的分区,即Queue,每个Queue大小相同。
消息标识:
RocketMq中每个消息拥有唯一的MessageId,且可以携带具有业务标识的key,以方便对消息的查询。
MessageId有两个:在生产者send()消息的时候会自动生成一个MessageId(msgId),当消息到达Broker后,Broker会自动生成一个MessageId(offsetMsgId)。msgId和offsetMsgId与key都成为消息标识。
msgId:由producer端生成,生成规则:
produceIp+进程pid+messageclientIDSetter类的classLoader的hashCode+当前时间+ AutomicInteger自增计数器
offsetMsgId:由broker端生成。brokerIp+物理分区的offset(Queue中的偏移量)
key:由用户指定的业务相应的唯一标识

系统架构:
Producer:消息生产者,负责生产消息。Producer通过MQ的负载均衡模块选择相应的Broker集群队列进行消息投递,投递的过程支持快速失败并且低延迟。—》生产者是以生产者组的形式出现的。一个生产者组可以同时发送多个主题的消息。
Consumer:消息消费者,负责消费消息。一个消息消费者会从Broker 服务器中获取到消息,并对消息进行相应业务处理。消费者是以消费者组的形式出现的。消费者组是同一类消费者的集合。这类Consumer消费的是同一个Topic类型的消息。
其实现的
负载均衡:(将一个Topic中的不同的Queue平均分配给同一个Consumer Group的不同的Consumer)
容错:(一个Consumer关了,该Consumer Group中的其他Consumer可以接着消费远Consumer消费的Queue)
Broker:Broker充当着消息中转角色,负责存储消息、转发消息。Broker在RocketMQ系统中负责接收并存储生产者发送来的消息,同时为消费者的拉去请求做准备。Broker同时也存储着消息相关的元数据,包括消费者组消费进度便宜offset、主题、队列等。
其模块:
Remoting Moudle:整个Broker 的实体,负责处理来自clients端的请求。该实体包含的模块有
1、ClientManager:客户端管理器。负责接收、解析客户端请求,管理客户端
2、Store Service:存储服务。处理消息存储到物理磁盘和消息查询功能
3、HA Service:高可用服务,提供 Mater Broker和Slave Broker之间的数据同步功能
4、Index Service:索引服务。根据特定的Message key,对投递到Broker的消息进行索引服务,同时也提供根据Message Key对消息进行快速查询的功能
集群部署:
为了增强Broker性能与吞吐量,Broker一般都是以集群形式出现.如何保证数据不丢失?其解决方式是将每个Broker集群节点进行横向扩展,即将Broker节点在创建一个HA集群,结局单点的问题.
Broker节点集群是一个主从集群,即集群中具有Master与Slave两种角色.Master负责处理读写操作请求,而Slave负责对Master中的数据进行备份,当Master挂点了,Slave则会自动切换为Master去工作.所以这个Broker集群是一个主备集群. 一个Master可以包含多个Slave,但一个Slave只能隶属于一个Master.Master与Slave的对应关系是通过指定相同的BrokerName.不同的BrokerId来确定的.BrokerId为0标识Master,非0标识Slave.每个Slave与NameServer集群中的所有节点建立长连接,定时注册Topic信息到所有NameServer

NameServer:是一个Broker与Topic路由的注册中心,支持Broker 的动态注册与发现
NameServer的选择策略:
首先采用的是随机策略进行的选择,失败后采用的是轮询策略
主要实现两个功能:
1、Broker管理:接收Broker集群的注册信息并且保存下来作为路由信息的基本数据;提供心跳检测机制,检查Broker是否还存活
2、路由信息管理:每个NameServer中都保存着Broker集群的整个路由信息和用户客户端查询的队列信息。Producer和Consumer通过NameServer可以获取整个Broker集群的路由信息,从而进行消息的投递和消费。
路由注册:
NameServer通常也是以集群的方式部署,NameServer是无状态的–》(即NameServer集群中的各个节点间是无差异的,个节点间相互不进行信息通讯)。各个节点的数据的数据同步—》在Broker节点启动时,轮询NameServer列表,与每个NameServer节点建立长连接,发起注册请求。在NameServer内部维持着一个Broker列表,用来动态存储Broker的信息。
这里的无状态方式的优缺点:
优点:NameServer集群搭建简单,扩容简单
缺点:对于Broker,必须明确指出所有NameServer地址。否则未指出的将不会注册,因此,NameServer并不能随便扩容。若Broker不重新配置,新增的NameServer对于Broker来说是不可见的名气不会向这个NameServer进行注册。
Broker注册:Broker节点为了维护与NameServer间的长连接,会将最新的信息以心跳包的方式上报给NameServer,每30秒发送一次心跳。心跳中包含BrokerId、Broker地址、Broker名称、Broker所属集群名称。NameServer在接收到心跳包后,会更新心跳时间戳,记录这个Broker 的最新存活时间
路由剔除:NameServer有一个定时任务,每隔10秒就会扫描一次Broker表,查看每一个Broker的最新心跳时间戳距离当前时间是否超过120秒(2分钟),如果超过,则会判定Broker失效,然后将其从Broker列表中剔除。
路由发现:RocketMq的路由发现采用的是Pull模型。当Topic路由信息出现变化时,NameServer不会主动推送给客户端,而是客户端每30秒会拉去一次最新的路由。
常见模型:
1、push模型:推送模型。实时性较好。需要维护一个长连接,而长连接的维护是需要资源成本的。使用场景:Client数量不多,Server数据变化较频繁。
2、pull模型:拉取模型。存在的问题:实时性较差
3、Long Polling模型:长轮询模型。其是对Push与Pull模型的整合,充分利用了这两种模型的优势,屏蔽了他们的劣势
Topic:区分消息的种类
MessageQueue:相当于是Topic的分区,用于并行发送和接收消息。
工作流程:
1.启动NameServer,NameServer启动后开始监听端口,等待Broker,Producer,Consumer连接.
2.启动Broker时,Broker会与所有的NameServer建立保持长连接,然后每30秒向NameServer定时发送心跳包.
3.发送前,可以先创建Topic,创建Topic需要指定该Topic要存储在那些Broker上,当然,在创建Topic时也会将Topic与Broker的关系写入到NameServer中.(这步是可选的,也可以在发送消息的时候自动创建Topic)
---->手动创建Topic有两种模式:
1.集群模式:
该模式下创建的Topic在该集群中,所有Broker中的Queue数量是相同的
2.Broker模式
该模式下创建的Topic在该集群中,每个Broker的Queue的数量可以不同
----->自动创建Topic时,默认采用的Broker模式,会为每个Broker默认创建4个Queue
(1).单Master,只有一个Broker(其本质上称不上集群)
(2)多Master :broker集群金由多个master构成,不能再salve.同意Topic的各个Queue会平均分布在各个master节点上
优点:配置简单,单个Master宕机或重启维护对应用无影响,在磁盘配置为RADID10磁盘,即使机器宕机不可恢复情况下,由于RADID10磁盘非常可靠,消息也不会丢失(异步刷盘会丢失少量数据,同步刷盘一条也不丢),性能最高
---->RADID10:磁盘阵列
----> 优点的前提是这些Master都配置了RAID10磁盘阵列.一旦没有配置,一旦出现某Master宕机,则会发生大量消息丢失的情况.
缺点:单台机器宕机期间,这台机器上未被消费的消息在机器恢复之前不可订阅(不可消费),消费者实时性会受到影响.
(3).多Master多Slave----异步复制:broker集群由多个master构成,每个master又配置了多个slave(在配置了RAID磁盘阵列的情况下,一个master一般配置一个slave即可).master与slave的关系是主备关系,即master负责处理消息的读写请求,而slave仅负责消费的备份与master宕机后的角色切换.(当master宕机后slave能够自动切换为master.不过由于slave从master的同步具有短暂的延迟(毫秒级),所以当master宕机后,这种异步复制方式可能会存在少量消息的丢失问题)
---->若Master的RAID此盘阵列,若使用的也是异步复制策略,同样也存在延迟问题,同样也可以会丢失消息,但RAID阵列的单位是微秒级的(因为是由硬件丢失的),所以丢失的数据量会更少
(4)多Master多Slave模式-同步双写:该模式是多Master多Slave模式的同步复制实现.所谓同步双写,值得是消息写入master成功后,master会等待slave同步数据成功后才向producer返回成功ACK,即master与slave都要写入成功后才能返回成功ACK.(该模式与异步模式相比,优点是消息的安全性高,不存在消息丢失的情况.但单个消息的RT略高,从而导致性能要略低(大越低10%))
---->该模式存在一个大的问题,对于目前的版本(4.9),Master宕机后,Slave不能自切换到Master

多Master+RAID阵列,与多Master多Slave集群的区别是什么?
1.多Master+RAID阵列,其仅仅可以保证数据不丢失,即不影响消息写入,但其可能会影响到消息的订阅. 但是他的效率要远高与多Master多Slave集群
2.多Master多Slave集群,其不仅可以保证数据不丢失,也不会影响消息写入.其运行效率要低于多Master+RAID阵列

4.Producer发送消息,启动时先跟NameServer集群中的其中一台建立长连接.并从NameServer中获取路由信息.发送的是Topic消息的Queue与Broker的地址(ip+Port)映射关系.然后根据算法策略从队列选择一个Queue,与队列所在的Broker建立长连接从而向Broker发送消息.当然,在获取到路由信息后,Producer会首先将路由信息缓存到本地,再每30秒从NameServer更新一次路由信息
5.Consumer跟Producer类似,跟其中一台NameServer建立长连接,获取其所订阅Topic的路由信息,然后根据算法策略从路由信息中获取到其索要消费的Queue,然后直接跟Broker建立厂里长连接,开始消费其中的消息.Consumer在获取路由信息后,同时也会每30秒从NameServer更新一次路由信息.(不同于Producer的是,Consumer还会像Broker发送 心跳,以确保Broker的存活状态)

读/写队列
从物理上来讲,读/写队列是同一个队列.所以,不存在读/写队列数据同步问题.一般情况下,读/写队列数量是相同的.
创建Topic时设置的写队列数量为4,读队列数量为8,此时系统会创建8个Queue.Producer会创建8个 但是Consumer明面上消费4个 但实际上是消费了8个,因为那四个是没有消息.
当读/写队列数量设置不同时,会有问题.这样设计的目的是为了Queue的缩容.
如何缩容从而不丢失消息?
1.可以动态修改写队列数量为8,读队列数量不变.此时新的消息只能写入前8个队列,而消费者消费的却是16个队列的数据,而发现8个Queue中的消息消费完毕后,就可以在将读队列数量动态设置为8.

Linux:部署
1.Linux改主机名称 Windows改主机名称
2.改Linux的ip地址

数据复制与刷盘策略
复制策略:是Broker的Master与Slave之间的数据同步方式.,分为同步复制和异步复制.
—>同步复制:消息写入master后,master会等待slave同步数据成功后猜想producer返回ACK
---->异步复制:消息写入master后,master立即向producer返回成功ACK,无需等待slave同步数据成功.(该策略会降低系统的写入延迟,RT变小,提高了系统的吞吐量)
刷盘策略:是Broker中消息的落盘方式,
—>落盘:消息发送到broker内存后消息持久化磁盘的方式.分为同步刷盘和异步刷盘
—>同步刷盘:当消息持久化到broker的磁盘后才算是消息写入成功
—>异步刷盘:当消息写入到broker的内存后即标识消息写入成功,无需等待消息持久化到磁盘(该策略会降低系统的写入延迟,RT变小,提高了系统的吞吐量)
消息写入到Broker的内存,一般是写入到了PageCache
对于异步刷盘策略,消息会写入到pageCache后立即返回成功ACK.但是并不会理解做落盘操作,而是当PageCache达到一定量时会自动进行落盘

RocketMQ工作原理
1、消息的生产过程:
(1)、Producer(生产者)发送消息之前,会先向NameServer 发出获取消息Topic的路由信息请求
(2)、NameServer返回该Topic的路由表及Broker列表
—》路由表:实际上是一个Map,key为topic名称,value是一个QueueData实例列表。QueueData 并不是Queue对应一个QueueData,而是一个Broker 中该Topic的所有Queue对应一个QueueData。QueueData中包含brokerName。
—》Broker列表:实际也是一个Map。key为brokerName,value为BrokerData。一套BrokerName名称相同的Master Slave 小集群对应一个BrokerData。BrokerData中包含brokerName及一个map。该map的key为brokerId,value为该broker对应的地址。brokerId为0标识broker为Master,非0标识Slave
(3)、Producer根据代码中指定的Queue选择策略,从Queue列表中选出一个队列,用于后续存储消息
(4)、Producer对消息做一些特殊处理
(5)、Producer向选择出的Queue所在的Broker发出RPC请求,将消息发送到选择出的Queue

Queue选择算法:
1、轮询算法:保证了每个Queue中可以均匀的获取到消息
—》该算法存在一个问题:由于某些原因,在某些Broker上的Queue可能延迟较严重。从而导致Producer的缓存队列中出现较大的消息积压,影响消息的投递性能
2、最小投递延迟算法:会统计每次消息投递的时间延迟,然后根据统计出的结果将消息投递到时间延迟最小的Queue。如果延迟相同,则采用轮询算法投递
—》该算法存在一个问题:消息在Queue上的分配不均匀。投递延迟小的Queue其可能存在大量的消息,而对该Queue消费者压力会增大,降低消息的消费能力,可能会导致MQ中消息的堆积
消息单元:
消息总长+物理地址+消息体+消息长度+生产者+消息发送的时间戳+主题+消息所在的队列QueueId+消息在Queue中存储的偏移量QueueOffset等
commitlog与queue间的关系是什么?(待整理)
一个mappedFile文件中第n个消息单元的commitlog offset偏移量

Consumequeue:
为了提升效率。会为每个Topic在该目录中创建一个目录,目录名为Topic名称。在该Topic目录下,会在为每个该Topic的Queue建立一个目录,目录名为queueId。每个目录中存放着若干consumequeue文件,该文件是commitlog的索引文件,可以根据consumequeue定位到具体的消息。
该consumequeue中的数据是顺序存放的,还引入了pageCache的预读取机制,是的对consumequeue文件的读取几乎接近于内存读取,即使由消息堆积情况下也不会影响性能
PageCache机制,缓存机制,是OS对文件的缓存机制,用于加速对文件的读写操作。一般来说,程序对文件进行顺序读写的速度几乎接近与内存读取速度,主要原因是由于OS使用PageCache机制对读写访问操作进行性能优化,将一部分的内存用作PageCache
----》写操作:OS会先将数据写入到PageCache中,随后以异步方式由pdflush内核线程将Cache中的数据刷盘到物理磁盘
----》读操作:若用户要读取数据,其首先会从PageCache中读取,若没有命中,则OS从物理磁盘上加载该数据到PageCache的同时,也会顺序对其相邻数据块中的数据进行预读取
索引条目:
每个索引条目包含三个消息重要属性:
1、消息在mappedFile文件中的偏移量、
2、消息长度、
3、消息Tag的hashcode值
一个comsumequeue文件中的所有消息的Topic一定是相同的。但每条消息的Tag可能不同的

消息的写入:
1、Broker根绝queueId,获取到该消息对应索引条目在consumequeue目录中的写入偏移量,即QueueOffset
2、将queueId、queueOffset等数据,与消息一起封装为消息单元
3、将queueId、queueOffset等数据,与消息一起封装为消息单元
4、将消息单元写入到commitlog
5、同时形成消息索引条目
6、将消息索引条目分发到相应的consumequeue

消息的拉取:
1、Consumer获取到其要消费消息所在Queue的消息偏移量offset(消费offset即消息进度,consumer对某个Queue的消费offset,即消费到了该Queue的第几条消息),计算出其消费消息的消息offset(该消息offset=消费偏移量offset+1)
2、Consumer向Broker发送拉取请求,其中会包含其要拉去消息的Queue、消息offset及消息Tag
3、Broker计算在该consumequeue中的queueOffset(该queueOffset等于消息Offset*20字节)
4、从该queueOffset处开始向后查找第一个Tag的索引条目
5、解析该索引条目的前8个字节,即可定位到该消息在commitlog中的commitlog offset
6、从对应commitlog offset中读取消息单元,并发送给Consumer

IndexFile
提供一个根据key对其进行查询

目录结构:
每个Broker中会包含一组indexFile,每个indexFile都是以一个时间戳命名的。
由三部分构成:indexHeader,stots槽位,indexes索引数据

消费模式:
1、广播模式:
广播模式下,相同Consumer Group的每个Consumer实例都接收同一个Topic的全量消息。即每条消息都会发送到Consumer Group的每个Consumer
2、集群模式:
集群模式下,相同Consumer Group的每个Consumer实例平均分摊同一个Topic的消息。即每条消息指挥被发送到Consumer Group的某个Consumer
消息进度保存:
广播模式:消息进度保存在consumer端。因为广播模式下Consumer Group中每个consumer都会消费所有消息,但他们的消费进度不同。
集群模式:消息进度保存在broker中。sumer group中的所有consumer共同消费同一个Topic中的消息,同一条消息只会被消费一次。

Rebalance机制(前提是在集群模式下)
什么是Rebalance?
—》Rebalance即再均衡,指的是,将一个Topic下的所有Queue、在同一个Consumer Group中的多个Consumer间进行重新配的过程。
作用:提升消息的并行消费能力

Relbalance产生原因(当产生的时候立刻向Consumer Group中的每个实例发出Rebalance通知,Consumer实例在接收到通知后会采用Queue分配算法 获取相应的Queue.由Consumer实例自主进行Rebalance)
1.消费者所订阅的Topic的Queue数量发生变化
Queue发生变化场景:
(1).Broker扩容或缩容
(2)Broker升级运维
(3)Broker与NameServer间的网络异常
2.消费者组中消费者的数量发生变化
发生变化场景:
(1)Consumer Group扩容或缩容
(2)Consumer升级运维
(3)Consumer与NameServer间网络异常
Rebalance限制
当消费者数量大于队列的数量时,多余的消费者实例将分配不到任何队列
Rebalance危害
1、消息暂停
2、消息重复
—》异步提交(默认):commer提交了其消费完毕的一批消息的offset给broker后,不需要等待broker的成功ACK。(消息会出现重复的原因,问题----》在异步提交下如何使消息不重复?未解)
—》同步提交:commer提交了其消费完毕的一批消息的offset给broker后,需要等待broker的成功ACK。只有收到ACK后,consumer才会继续获取并消费下一批消息。
3、消息突刺:重复消费的消息过多,或因为Rebalance暂停时间过程使消息积压。给消费者造成巨大的压力

Queue分配算法
平均分配策略:(Queue数量/Consumer数量)
先算好每个Consumer应该分得几个Queue,然后在依次将这些数量的Queue逐个分配
环形平均策略:
根据消费者的顺序,一次在由Queue队列组成的环形图中诸葛分配.(是否能解决消息消费按照顺序消费的问题?未解决)
一致性hash策略:
将consumer的hash值作为Node节点存放到hash环上,然后将queue的hash值也放到hash环上,通过逆时针方向,距离queue最近的那个consumer就是该queue要分配的consumer
—>会出现的分配不均的问题
同机房策略:
会根据queue的部署机房位置和consumer的位置,过滤出当前consumer相同机房的queue.然后按照平均分配策略或环形平均策略对同机房queue进行分配.如果没有同机房queue,则按照平均分配策略或环形平均策略对所有queue进行分配…

至少一次原则:
每条消息必须要成功消费一次(只有当Consumer在消费完消息向其消费进度记录器提交其消费消息的offset,offset被成功记录到记录器中,那者条消息才是被成功消费了给v发突破,kk)
消费进度记录器?
广播模式–>Consumer本身就是消费进度记录器
集群模式–>Broker是消费进度记录器
死信消息:消费者消费消息,达到失败重试次数后仍然失败时,Rocketmq会以消费者组为单元,将消费失败的消息放入一个特定的队列中,这个队列就是死信队列。(死信队列的topic是%DLQ%+消费者组的名称)

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值