分模块详解 RocketMQ 架构原理
Posted 小王曾是少年
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了分模块详解 RocketMQ 架构原理相关的知识,希望对你有一定的参考价值。
🍊 Java学习:Java从入门到精通总结
🍊 深入浅出RocketMQ设计思想:深入浅出RocketMQ设计思想
🍊 绝对不一样的职场干货:大厂最佳实践经验指南
📆 最近更新:2022年5月14日
🍊 个人简介:通信工程本硕💪、Java程序员🌕。做过科研,发过专利,优秀的程序员不应该只是CRUD
🍊 点赞 👍 收藏 ⭐留言 📝 都是我最大的动力!
文章目录
RocketMQ 总体架构
上图里的虚线表示数据同步过程,目的是保证数据的最终一致性。
从上图可以看出,RabbitMQ使用了一个注册中心作为发现与注册服务器,Producer
向Broker
发送消息,Consumer
从Broker
处接收消息,Broker
使用主从结构来进行消息的存储(为了方便理解,我画了最经典的一主三从结构)。
接下来,我们将对每一个部分做更详细的拆解分析。
注册中心
在RocketMQ里,注册中心使用的是nameserver
,原因是它具有稳定性高的特点,集群部署时单台nameserver
挂掉并不会影响其它的,即使全部nameserver
挂掉,也可以使用最近一次的注册信息来提供服务,不影响整体业务。
nameserver
不会有频繁的读写,所以性能开销很少,稳定性也高。
在RocketMQ里,注册中心每隔10s会扫描一次所有的Broker
,如果发现某个Broker
已经连续2min没有发送心跳过来了,就认为其挂了,断开连接。此时注册中心会更新Topic
与队列的对应关系,但不会通知Producer
和Consumer
。
Broker 架构
Broker
通常以集群的形式运行,存储Producer
发来的消息。
与注册中心的交互:
- 每个
Broker
和所有的注册中心保持长连接 - 每30s向注册中心发送心跳,心跳里面有自身的
Topic
信息
负载均衡设计:
Broker
和Topic
是多对多的关系,一个Topic
会分布在多个Broker
上,一个Broker
里也会有多个Topic
- 如果某个
Topic
收到的消息很多,则应该给它配置多个队列,并让这些队列尽量平均分在多个Broker
上
高可用设计:
RocketMQ采用主从结构来保证高可用,Master负责消息的写入,多个Slave负责消息的读取,Slave定期从Master处同步数据,保证最终一致性,如果Master挂了,可以由Slave继续提供度服务,并重新投票选举出新的Master。
这里有两个关键细节需要注意:
- 一旦
Broker
挂了,由于RocketMQ的心跳机制实现细节,Producer
和Consumer
最多30s才能够发现,在这一段时间里,发往这个Broker的消息都会发送失败,并且也没有办法消费消息 - RocketMQ保证的是最终一致性,所以会出现有一部分数据没来得及同步给Slave,Master就挂了的情况,但一旦Master回复之后,就又可以重新同步不一致的数据
高可靠设计:
- 所有收到的消息都会有同步和异步的刷盘机制,也就是将数据保存在硬盘上,可靠性很高
- 同步刷盘时,只有写入成功了才会返回成功
- 异步刷盘时,只有服务器宕机了才会丢失数据,这个概率是非常小的
读写性能:
- 使用了Linux系统的特性:以文件内存映射方式操作文件,避免read/write用户态和核心态的多次切换,性能很高
- 使用了顺序写IO,也会提高效率
- 读写分离,极大程度的缓解写锁和读锁的争用
除此之外,RocketMQ还提供了其他的功能及特性。
消息清理:
- 清理时机:默认是每天凌晨4点,或者磁盘空间不足时清理
- 磁盘空间阈值:默认阈值是85%,也就是当磁盘空间被占了超过85%之后会触发清理过程
- 消息写入磁盘文件后默认保存时间是72h
对此,我们也可以总结一下RocketMQ对服务器的硬件要求:
- 内存占用高
- 属于IO密集型应用,这种应用的特点是CPU附在高但使用率较低,大部分时间是在等待IO操作
- 硬盘要求高,这样数据持久化就会很快
消费者架构
与注册中心的交互:
- 一个
Consumer
与注册中心的一台服务器保持长连接,并且会定时查询MQ的Topic
配置信息,如果当前注册中心的服务器宕机,Consumer
会自动与下一台服务器连接 - 在保持长连接的情况下,
Consumer
每30s获取一次配置中心的所有Topic
配置信息,如果某个Broker
宕机,Consumer
最多需要30s可以从配置中心感知到(如果读消息多次失败也可以感知到)
与Broker
的交互:
Consumer
及与之关联的Broker
之间保持长连接Consumer
默认每隔30s向与之关联的Broker
发送心跳;Broker
每10s扫描所有的长连接,如果某个连接2min内没有发送心跳数据,则关闭连接,并且通知消费者组里的其他消费者重新按照策略分配队列消费
负载均衡设计:
- 一个
Consumer
集群里的每个Consumer
只消费一个队列,如果某个Consumer
挂了,则他的任务会被同组内Consumer
接替
消费消息过程:
- RocketMQ采用拉模型,
Consumer
不断拉取消息到本地来消费。拉取消息和消费消息是一个异步操作,所以就需要一个数据结构来存储拉下来的消息,这就是本地队列 - 默认每隔5s,RocketMQ就会将各个队列的消息消费进度存储到对应的
Broker
上 - 消费者拉取队列里的消息时,会将消息拉取任务放在本地的线程执行队列里逐次执行,执行完毕后再将任务放到队尾,依次循环
生产者架构
与注册中心的交互:
- 一个
Producer
与注册中心的一台服务器保持长连接,并且会定时查询MQ的Topic
配置信息,如果当前注册中心的服务器宕机,Producer
会自动与下一台服务器连接 - 在保持长连接的情况下,
Producer
每30s获取一次配置中心的所有Topic
的最新队列情况,如果某个Broker
宕机,Producer
最多需要30s可以从配置中心感知到(如果写入消息多次失败也可以感知到)
与Broker
的交互:
Producer
及与之关联的Broker
之间保持长连接Producer
默认每隔30s向与之关联的Broker
发送心跳;Broker
每10s扫描所有的长连接,如果某个连接2min内没有发送心跳数据,则关闭连接
以上是关于分模块详解 RocketMQ 架构原理的主要内容,如果未能解决你的问题,请参考以下文章