(1)RocketMQ整体架构
RocketMQ整体架构包含了4中角色:
- NameServer
- Broker
- Producer
- Consumer
其中NameServer主要用于管理整个集群的元数据以及对集群进行管理的。
Broker相当于单个节点负责数据的读写的,而Producer就是负责生产消息后写入Broker的,Consumer则是从Broker来消费消息。
而且Broker在部署的时候,一般是分为主备角色的。也就是说,每个Broker都部署一个Master角色在一台机器上,然后另外会部署一个Slave角色在另外一台机器上。
这样如果某个Broker Master挂了,他的Broker Slave就可以接替继续工作,保证了高可用。
下图阐述了RocketMQ的整体架构原理:
(2)RocketMQ工作流程
首先需要先启动NameServer,接着启动Broker
Broker启动之后就会跟NameServer建立长连接,每隔一段时间发送心跳包过去
心跳包里需要包含自己当前存储的数据信息,让NameServer感知到各个Broker的情况,如下图:
创建Topic的时候决定Topic的数据会放在哪个Broker上。
每个Broker在进行心跳的时候,就可以上报自己当前存储的Topic相关的数据给NameServer知道。
而NameServer就保存了整个集群的元数据,知道每个Topic当前数据保存在哪些Broker上,如下图:
Producer在生产消息到Topic的时候,先得找NameServer问一下Topic存放在哪些Broker上,然后就可以跟那些Broker建立连接发送消息过去了。
Consumer要从Topic消费消息,也会找NameServer问一下可以从哪些Broker上消费消息,接着同样会跟Broker建立连接并且开始消费消息,如下图。
(3)NameServer原理分析
NameServer一般是集群化部署,各个机器上部署的NameServer会相互同步收集到的元数据,保证各个NameServer上包含的集群元数据都是相同的。这样的架构可以保证即使任何一个NameServer宕机了也不要紧。
NameServer主要责任就是管理Broker的心跳,如果一段时间内没有心跳,则认为那个Broker已经宕机了,此时要触发对应的Slave切换为Master保证高可用。
此外,NameServer还要负责管理和维护集群元数据,比如有哪些Topic,每个Topic在哪些Broker上。
NameServer承受的请求压力是很小的,因为心跳和拉取元数据,其实是很低频的行为,所以一般部署两三台机器就足够了。
但是需要注意的是 ,如果集群里维护了几十万个,甚至几百万个Topic,会导致Broker每次心跳上报Topic数据时,带上几十万个Topic的数据信息,可能多达几十MB,那会导致心跳时网络负载过重。
(4)分布式架构分析
再说说Topic,每个Topic都由很多个队列组成,一个队列代表了这个Topic的部分数据,然后这个Topic的多个队列会均匀分散在多个Broker上。
比如说Topic有6个队列,对应三台Broker,那么每个Broker上就可以放2个队列的数据。
这样就可以做到每个Topic的数据都可以分布式存储在集群中的多台Broker上,形成了分布式的存储架构,这样就可以利用多台机器的资源来存储数据
同时,可以利用多台机器的资源来应对高并发的请求,因为对一个Topic的读写请求,就会均匀的落到多台Broker机器上去了。
如下图所示,可以看到数据分布式存储的架构。
(5)Broker原理分析
Broker主要就两点:负责接收Producer写入的消息,同时提供消息给Consumer来读取。
写入消息时,Broker可以实现高并发高性能的写入。
这个主要采用的是对磁盘文件进行顺序写的方式,磁盘顺序写的性能是很高的,几乎跟内存随机读写的性能差不多。
另外,就是优先把数据写入os page cahce,也就是操作系统管理的缓存中。
写操作系统的内存缓存,那性能就更高了,不需要每次都直接写入物理磁盘中。
读取消息时,Broker也是主要基于os page cahce读取消息,也就是优先从操作系统管理的内存缓存中读取数据,提供给Consumer来消费。因为是优先读内存,所以同样性能也是很高的。
通过这种架构,Broker就可以保证高并发以及高性能。
另外,Broker还实现了高可用的架构。也就是说每个Broker Master都会把自己接收到的数据同步给Broker Slave,实现每个Broker上的数据备份。
如果Broker Master宕机了,会切换Broker Slave对外提供服务,保证了高可用的架构。
(6)Consumer原理分析
如果我们部署了Consumer在多台机器上,默认也会把Topic下的多个队列的数据均匀的分配给各个Consumer实例来进行消费。
比如Topic下一共6个队列,假设部署了3个Consumer实例,此时每个Consumer实例就会消费2个队列的数据,如下图:
(7)总结
对于任何一个消息系统,对他的原理进行研究的时候,都应该关注几点:
- 集群架构(元数据如何管理、集群如何管理)
- 数据模型(Topic、队列等概念)
- 分布式架构(消息如何分布式存储)
- 消息写入以及读取的原理
- 高可用架构(如何进行数据冗余)
- 客户端原理
把这些弄明白之后,才算对一个消息系统有了一定的了解,才能开始尝试把这个消息系统应用于自己公司的生产项目中。