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
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 被坑几百块钱后,我竟然真的恢复了删除的微信聊天记录!
· 没有Manus邀请码?试试免邀请码的MGX或者开源的OpenManus吧
· 【自荐】一款简洁、开源的在线白板工具 Drawnix
· 园子的第一款AI主题卫衣上架——"HELLO! HOW CAN I ASSIST YOU TODAY
· Docker 太简单,K8s 太复杂?w7panel 让容器管理更轻松!
2019-04-16 第三章:垃圾回收器-参数总结