分模块详解 RocketMQ 架构原理

Java学习:Java从入门到精通总结

深入浅出RocketMQ设计思想:深入浅出RocketMQ设计思想

绝对不一样的职场干货:大厂最佳实践经验指南


最近更新:2022年5月14日

个人简介:通信工程本硕、Java程序员。做过科研,发过专利,优秀的程序员不应该只是CRUD

点赞 收藏 ⭐留言 都是我最大的动力!

文章目录

    • RocketMQ 总体架构
    • 注册中心
    • Broker 架构
    • 消费者架构
    • 生产者架构

RocketMQ 总体架构

分模块详解 RocketMQ 架构原理_第1张图片
上图里的虚线表示数据同步过程,目的是保证数据的最终一致性。


从上图可以看出,RabbitMQ使用了一个注册中心作为发现与注册服务器,ProducerBroker发送消息,ConsumerBroker处接收消息,Broker使用主从结构来进行消息的存储(为了方便理解,我画了最经典的一主三从结构)。

接下来,我们将对每一个部分做更详细的拆解分析。


注册中心

在RocketMQ里,注册中心使用的是nameserver,原因是它具有稳定性高的特点,集群部署时单台nameserver挂掉并不会影响其它的,即使全部nameserver挂掉,也可以使用最近一次的注册信息来提供服务,不影响整体业务。

nameserver不会有频繁的读写,所以性能开销很少,稳定性也高。


在RocketMQ里,注册中心每隔10s会扫描一次所有的Broker,如果发现某个Broker已经连续2min没有发送心跳过来了,就认为其挂了,断开连接。此时注册中心会更新Topic与队列的对应关系,但不会通知ProducerConsumer


Broker 架构

Broker通常以集群的形式运行,存储Producer发来的消息。


与注册中心的交互:

  1. 每个Broker和所有的注册中心保持长连接
  2. 每30s向注册中心发送心跳,心跳里面有自身的Topic信息

负载均衡设计:

  1. BrokerTopic是多对多的关系,一个Topic会分布在多个Broker上,一个Broker里也会有多个Topic
  2. 如果某个Topic收到的消息很多,则应该给它配置多个队列,并让这些队列尽量平均分在多个Broker

高可用设计:
RocketMQ采用主从结构来保证高可用,Master负责消息的写入,多个Slave负责消息的读取,Slave定期从Master处同步数据,保证最终一致性,如果Master挂了,可以由Slave继续提供度服务,并重新投票选举出新的Master。


这里有两个关键细节需要注意:

  1. 一旦Broker挂了,由于RocketMQ的心跳机制实现细节,ProducerConsumer最多30s才能够发现,在这一段时间里,发往这个Broker的消息都会发送失败,并且也没有办法消费消息
  2. RocketMQ保证的是最终一致性,所以会出现有一部分数据没来得及同步给Slave,Master就挂了的情况,但一旦Master回复之后,就又可以重新同步不一致的数据

高可靠设计:

  1. 所有收到的消息都会有同步和异步的刷盘机制,也就是将数据保存在硬盘上,可靠性很高
  2. 同步刷盘时,只有写入成功了才会返回成功
  3. 异步刷盘时,只有服务器宕机了才会丢失数据,这个概率是非常小的

读写性能:

  1. 使用了Linux系统的特性:以文件内存映射方式操作文件,避免read/write用户态和核心态的多次切换,性能很高
  2. 使用了顺序写IO,也会提高效率
  3. 读写分离,极大程度的缓解写锁和读锁的争用

除此之外,RocketMQ还提供了其他的功能及特性。

消息清理:

  1. 清理时机:默认是每天凌晨4点,或者磁盘空间不足时清理
  2. 磁盘空间阈值:默认阈值是85%,也就是当磁盘空间被占了超过85%之后会触发清理过程
  3. 消息写入磁盘文件后默认保存时间是72h

对此,我们也可以总结一下RocketMQ对服务器的硬件要求:

  1. 内存占用高
  2. 属于IO密集型应用,这种应用的特点是CPU附在高但使用率较低,大部分时间是在等待IO操作
  3. 硬盘要求高,这样数据持久化就会很快



消费者架构

与注册中心的交互:

  1. 一个Consumer与注册中心的一台服务器保持长连接,并且会定时查询MQ的Topic配置信息,如果当前注册中心的服务器宕机,Consumer会自动与下一台服务器连接
  2. 在保持长连接的情况下,Consumer每30s获取一次配置中心的所有Topic配置信息,如果某个Broker宕机,Consumer最多需要30s可以从配置中心感知到(如果读消息多次失败也可以感知到)

Broker的交互:

  1. Consumer及与之关联的Broker之间保持长连接
  2. Consumer默认每隔30s向与之关联的Broker发送心跳;Broker每10s扫描所有的长连接,如果某个连接2min内没有发送心跳数据,则关闭连接,并且通知消费者组里的其他消费者重新按照策略分配队列消费

负载均衡设计:

  1. 一个Consumer集群里的每个Consumer只消费一个队列,如果某个Consumer挂了,则他的任务会被同组内Consumer接替

消费消息过程:

  1. RocketMQ采用拉模型,Consumer不断拉取消息到本地来消费。拉取消息和消费消息是一个异步操作,所以就需要一个数据结构来存储拉下来的消息,这就是本地队列
  2. 默认每隔5s,RocketMQ就会将各个队列的消息消费进度存储到对应的Broker
  3. 消费者拉取队列里的消息时,会将消息拉取任务放在本地的线程执行队列里逐次执行,执行完毕后再将任务放到队尾,依次循环



生产者架构

与注册中心的交互:

  1. 一个Producer与注册中心的一台服务器保持长连接,并且会定时查询MQ的Topic配置信息,如果当前注册中心的服务器宕机,Producer会自动与下一台服务器连接
  2. 在保持长连接的情况下,Producer每30s获取一次配置中心的所有Topic的最新队列情况,如果某个Broker宕机,Producer最多需要30s可以从配置中心感知到(如果写入消息多次失败也可以感知到)

Broker的交互:

  1. Producer及与之关联的Broker之间保持长连接
  2. Producer默认每隔30s向与之关联的Broker发送心跳;Broker每10s扫描所有的长连接,如果某个连接2min内没有发送心跳数据,则关闭连接

你可能感兴趣的:(架构,java,rabbitmq)