RocketMQ特性

1、为什么需要消息队列

削峰填谷

程序间解耦

异步处理

数据的最终一致性

2、常见消息队列

消息队列 activeMQ kafka rocketMQ

特性

支持多种协议:AMQP、STMOP、MQTT、JMS

消息支持持久化

超高写入速率

端到端耗时毫秒级

万亿级消息支持

万级topic数量支持

端到端耗时毫秒级

管理后台 自带 独立部署 独立部署
多语言支持 支持 支持 java、c++、python、go、c#
数据流支持 不支持 支持 支持
消息丢失 理论上不丢失 理论上不丢失 理论上不丢失
文档完整性 好 极好 极好
商业化公司 国内部分企业 国内很多企业 阿里巴巴为主
容错 无重试机制 无重试机制 支持重试、死信消息
顺序消息 支持 支持 支持
定时消息 不支持 支持 支持
事务消息 不支持 不支持 支持
消息查询 数据库中查询 不支持 支持
宕机 自动切换 主动选主 手动重启

3、生产者

生产者组:一个生产者生产多个topic消息

生产者实例:一个生产者部署多个进程,每个进程都可以称为一个生产者实例

topic:主题名称,一个topic由若干个queue组成

4、消息组成

topic

properties:消息扩展信息,Tag、Keys、延迟级别都保持在这里

Body:消息体,字节数组,需要注解编码格式保持一致,防止消息乱码

setKeys:设置消息的key,可以根据key常见消息的hash索引,帮助快速查询

setTags:设置tag,一个topic可以设置不同的tag

setDelayTimeLevel:设置消息延迟级别

putUserProperty:如果有其他要扩展的信息,可以放在这个Map中

5、消息支持类型

普通消息:性能最好

分区有序消息:一个topic对应多个分区,分区使用FIFO原则

全局有序消息:一个topic对应一个分区

延迟消息:消息发送后一段时间后,消费者才可以被消费掉

事务消息:可以保证多个事务同时成功或者失败,机制时half消息、处理本地事务、提交消息、回滚消息的方式实现优雅的分布式事务

6、生产者高可用

客户端保证

重试机制:rocketMQ支持同步、异步方式,都可以在失败后重试,如果一个broker发生故障,可以找到其他可用的broker

客户端容错:客户端可以选择延迟级别最低的broker进行发送消息

Broker保证

数据同步分为同步复制、异步复制两种。

同步复制是指消息发送到master broker后,同步到slave broker才算发送成功。

异步复制是指消息发送到master broker后就算成功。

如果是多个master slave也是类似的方式。

如果想要保持绝对的高可用,将broker配置的主从同步进行复制即可,只要生产者收到消息保持成功就反馈,消息可定不会丢失。

7、消息发送流程

业务层:直接调用rocketMQ client 发送api的业务代码

消息处理层:rocketMQ client 获取业务发送的消息对象后,进行的一些列参数校验、发送准备、参数包装等操作

通信层:rocketMQ基于netty封装的一个rpc通讯协议

8、延迟消息

支持18个级别,从1S、5S、10S、30S、1M、2、3、4、5、6、7、8、9、10、20、30、1h、2h

9、事务消息

第一步先发送一个half消息到broker,Broker设置queueOffset=0,即对消费者不可见

第二笔用户本地事务提交成功后,发送一个commit到broker,broker修改queueoffset为正数值,达到投递目的,如果本地事务提交失败,则发送一个rollback消息给broker。

broker会定期回查生产者,确认生产者本地事务的执行状态,再决定是提交还是回顾还是删除half消息。

10、发送单向消息

主要是日志传输等消息允许丢失的常见

11、批量消息

消息最好小于1M

同一批消息的topic、waitStoreMsgOk属性必须一致

批量消息不支持延迟消息

12、生产者最佳实践

普通消息:性能最好、单机TPS10万级别,缺点是生产和消费都是无须、适用于大部分场景

分区消息:单机有序、单机TPS万级别、缺点是单点问题、如果broker宕机会导致消息发送失败、适用于大部分有序消息场景

 全局有序消息:类型传统queue、单机TPS千级别、单点问题、如果broker宕机会导致消息发送失败、适用场景极少

延迟消息:rocketMQ自身支持、不需要额外组件、缺点是不能根据任意时间延迟、非精确、延迟级别不够多、使用简单方便

事务消息:rocketMQ自身支持、不需要额外组件、缺点是生产者事务、只有生产者参与,如果消费者处理失败则事务无效、简单事务处理可以使用

13、同步与异步发送

同步发送:最可靠、性能最低、适用于高并发常见

异步发送:可靠、性能最高、如果发送失败需要考虑降级、大部分业务场景可以使用

14、常见配置参数

producerGroup生产者分组

消息体数量超过该值则压缩消息

instanceName生产者实例名

maxMessageSize消费体最大值,默认4M

retryXXX异步发送失败的重试次数

retryTimsWhenSendFailed同步发送失败的重试次数

senMsgTimeout发送超时时间

15、消费者概念

消费者组:一个逻辑概念,在使用消费者时要指定一个分组,一个消费者组可以订阅多个topic

消费者实例:一个消费者程序部署多个进程,每个进程都可以称为一个消费者实例

订阅关系:一个消费者组订阅一个topic的某个tag、这种记录被称为订阅关系,消费者分组-topic-tag必须是唯一的

16、消费模式

集群消费与广播消费

集群消费

同一个消费者分组了里的消费者实例,会负载均衡的消费topic

同一个topic会被不同的消费者分组里的消费者实例消费,即1个topic关联多个消费者分组

集群消费的进度保存在broker端,所以即使应用崩溃、消费进度也不会丢失

广播模式

即消费者组中的全部消费者实例将消费整个topic的全部消息

一个消费者分组中的两个消费者实例,每个消费者实例消耗相同数量的topic消息,不会进行负载均衡

17、可靠消息

重试消费(做多16次)、死信机制(超过16次则放入死信队列)

死信队列:命名格式“%DLQ%消费者组名”

18、rebalance机制

重平衡机制,用于在发现broker掉线、topic扩容或者缩容、消费者扩容和缩容等变化时,自动感知并调整自身消费,尽力减少甚至避免消费没有被消费。

19、消费进度保存机制

rocketMQ设计了远程位点管理和本地位点管理两种位点管理方式

集群消费时,位点管理由客户端交给broker管理

广播模式下,位点保存在消费者本地磁盘上(即使丢失了,也可以重复消费)

20、消费方式push与pull

pull方式:用户主动pull消息,自主管理位点,可以灵活掌控消费进度、消费速度,缺点时需要从代码层面精准控制消费

push方式:代码接入简单、排查问题方便、适用于大部分常见,缺点是灵活度差

21、rocketMQ架构

console控制台:创建topic、key查询消费

namesrv:一个无状态的元数据管理、类似与kafka中zookeeper的定位

broker集群:保存消息、处理生产者、消费者的各种请求的代理,包括master和slave两个角色

生产者集群:消费发送方

消费者集群:消息消费方

22、namesrv

部署推荐2~3个节点

23、broker部署方式

单个master、单master单slave、多个master无slave、多个master多个slave异步复制、多个master多个slave同步复制

24、刷盘

消息保持到内存后,可以同步、异步方式写到磁盘上

同步刷盘:生产者等待写入磁盘才返回发送成功

异步刷盘:生产者写入内存就可以返回发送成功

25、namesrv

主要保持管理topic路由信息(topic队列信息、broker信息、集群和broker对应关系、当前在线的broker地址、过滤服务器信息)、各个namesrv是无状态的,多个namesrv之间不需要同步信息、状态

在broker、生产者、消费者启动时,可以轮训全部配置的namesrv节点、拉取路由信息

Topic路由信息决定了topic信息发送到哪个broker,消费者从哪个broker消费消息

26、namesrv与zookeeper

不适用zookeeper的原因是减少依赖,通过简单的namesrv可以承担

27、namesrv流程

broker启动注册到namesrv中

生产者询问namesrv把消息发送到哪里

namesrv告诉消息发送到的broker

生产者发送消息到broker

消费者询问namesrv在哪里可以消费信息

namesrv告诉消费者具体的broker

消费者向指定broker拉取消息

28、namesrv核心组件

topic路由管理模块:信息发送到哪个broker、从哪个broker消费

remoting通讯模块:netty的一个通讯封装

定时任务模块:扫描宕机的broker、定时打印kv配置、定时扫描超时请求

29、路由注册

namesrv获取的topic路由信息来自broker的定时心跳、心跳时broker会将topic信息发送到namesrv。

30、路由剔除

broker主动剔除

namesrv定时扫描已下线的broker

 31、消费过滤

RocketMQ设计了消息过滤:即对于客户端不需要的消息,Broker不会传输给客户端,以避免浪费。

使用Tag进行过滤消息

过滤步骤:

1、用户发送一个带有tag的消息

2、用户订阅一个topic的tag,RocketMQ broker会保持订阅关系

3、在Broker端做tag过滤。消费者pull时RocketMQ broker会根据tag的hashcode进行比较,如果不满足条,不会返回给消费者。

4、客户端tag过滤,由于hashcode存在碰撞问题,所以还以在客户端进行字符串比较

32、消息问题排查

1、topic是否一致:生产者、消费者、控制台

2、订阅关系是否一致

3、消费者是否抛出了异常,如果没有抛出异常,消息不会进行重试

4、消费者服务器与namesrv或者broker是否网络通畅

33、Broker存储机制

Broker主要负责处理各种tcp请求和存储消息

Broker分为master和slave,master主要提供服务,slave在master宕机后提供消费服务。

34、Broker存储目录结构

commitlog:目录下有多个文件,文件名有该文件保存消息的最大物理offset值在高位补0组成。文件大小一般1G。

consumequeue:目录下包含该broker上所有的topic对应的消费队列文件信息。

Index:目录下的全部文件都是按照消息key创建的hash索引。

config:目录保存了当前Broker中全部topic、订阅关系和消费进度。

35、Broker启动与停止

第一步:初始化启动环境,包括启动./bin/mqbroker和./bin/runbroker.sh两个脚本,设计到JAVA_HOME、ROCKETMQ_HOME环境变量。

第二步:初始化BrokerController:RocketMQ命令行解析、Broker各个模块配置参数解析、Broker各个模块初始化、进程关机hook初始化等过程。

第三步:启动RocketMQ的各个组件:存储服务、普通请求处理服务、VIP请求处理服务、Broker访问对外接口的封装对象、Pull长轮训服务、清理心跳超时的生产者和消费者和过滤服务、过滤服务器。

36、Broker存储机制

消息会存储到commitlog中,为了方便保存和读取会把commitlog切分为多个文件

Broker按照时间和物理的offset顺序写commitlog文件,每次写的时候需要加锁。

37、为什么写文件很快

参考了kafka的设计

Page Cache:分页读取文件、整页读取可以进行预读

VM:虚拟内存,把暂时不需要的数据保存到磁盘(虚拟内存)

零拷贝与Java文件映射:Java进程可以直接读取到内核态的数据,不需要经过用户态转换

38、Broker消息存储流程

业务系统发送信息

->broker接收到客户端消息进行预处理:解析参数、执行发送处理前的hook、调用保存方法存储消息、执行发送处理后的hook。

->broker存储前进行预处理:设置请求处理返回对象标识

->执行putMessage方法进行消息校验和存储模块检查:存储模块是否已关闭、Broker是否是slave、存储模块运行标识、topic长度、扩展信息长度等

39、文件刷盘机制

同步与异常刷盘:内存数据保持到磁盘

同步刷盘:有一个后台线程服务

异步刷盘:如果broker配置了读写分离,则异步刷盘过程包含异步转存数据和真正的异步刷盘操作。

40、Broker读写分离

master与slave读写分离

直接写内存与读PageCache分离

41、Broker commitlog索引机制

Broker有两个索引:consumer queue和Index File

consumer queue:消费者队列,用于消费者拉取信息、更新消费点

Index File:是一个RocketMQ实现的hash索引,用于用户根据key查询消息

42、Broker过期文件删除机制

commitlog文件删除:当前时间大于已经配置的过期时间、磁盘使用空间超过85%、手动执行删除

步骤一:克隆全部commitlog文件,为了防止有数据写入

步骤二:检查每个commitlog是否过期

43、broker主从同步机制

第一:broker服务高可用,一般生产环境部署两个master、两个slave节点,一个master宕机后,另个一master会继续工作。

第二:提供服务性能,如果消费者发现行master拉取信息时,拉取的offset和commitlog物理offset相差太多,会转向slave拉取消息。

同步复制、同步刷盘

44、生产者启动流程

创建一个生产者实例,设置各种参数,比如namesrv地址、生产者组名等,调用star()方法创建生产者实例。

判断当前生产者的服务状态,默认状态为CREATE_JUST

执行checkConfig方法

执行changeInstanceNameToPID方法

执行getAndCreateMQClientInstance方法

45、消息发送流程

调用defaultMQProducer.send()方法

设置超时时间

设置同步发送

发送前check:生产者状态、消息、消息内容

选择topic、queue发送:获取topic路由信息

计算信息发送的重试次数,同步重试或者异步重试

执行sendKernel方法

46、消费者启动机制

调用DefaultMQPullConsumer的start()方法

检查消费者的配置,消费者组名、消费类型、Queue分配策略

检验消费者实例名

获取一个MQClientInstance

设置rebalance对象消费者组、消费类型、Queue分配策略等

对Broker api的封装类进行初始化

初始化位点管理器,并加载位点信息

本地注册消费者实例

启动MQClientInstance

posted @ 2024-04-16 00:42  使用D  阅读(163)  评论(0)    收藏  举报