Loading

RocketMQ学习:Broker

Broker

Broker充当着消息中转角色,负责存储消息、转发消息。 Broker在 Rocketmq系统中负责接收并存储从生产者发送来的消息,同时为消费者的拉取请求作准备。Broker同时也存储着消息相关的元数据,包括消费者组消费进度偏移 offset、主题、队列等。
image

  • Remoting Module:整个 Broker的实体,负责处理来自 clients端的请求。而这个Broker实体则由以下模块构成:

  • Client Manager:客户端管理器。负责接收、解析客户端( Producer/Consumer)请求,管理客户端。例如,维护 Consumer的Topic订阅信息

  • Store service:存储服务。提供方便简单的AP接口,处理消息存储到物理硬盘和消息査询功能。

  • HA Service:高可用服务,提供 Master broker和 Slave broker之间的数据同步功能。

  • Index service:索引服务。根据特定的 Message key,对投递到 Broker的消息进行索引服务,同时也提供根据 Message Key对消息进行快速查询的功能。

为了增强 Broker性能与吞吐量, Broker一般都是以集群形式岀现的。各集群节点中可能存放着相同Topic的不同 Queue。不过,这里有个问题,如果某 Broker节点宕机,如何保证数据不丢失呢?其解决方案是,将每个Broker集群节点进行横向扩展,即将 Broker节点再建为一个HA集群,解决单点问题。

Broker节点集群是一个主从集群,即集群中具有 Master与 Slave两种角色。Master负责处理读写操作请求,而 Slave仅负责读操作请求。一个 Maste可以包含多个 Slave,但一个 Slave只能隶属于个 Master。Master与 Slave的对应关系是通过指定相同的 BrokerName、不同的 BrokerId来确定的。BrokerId为0表示Master,非0表示Slave,每个Broker与NameServer集群中的所有节点建立长连接,定时注册Topic信息到所有 Nameserver。

工作流程

  1. 启动 NameServer, NameServer启动后开始监听端口,等待 Broker、 Producer、 Consumer连接。

  2. 启动 Broker时, Broker会与所有的 NameServer建立并保持长连接,然后每30秒向NameServer定时发送心跳包

  3. 发送消息前,可以先创建 Topic,创建 Topic时需要指定该 Topic要存储在哪些 Broker上,当然,在创建Topic时也会将 Topic与 Broker的关系写入到 NameServer中。不过,这步是可选的,也可以在发送消息时自动创建 Topic

  4. Producer发送消息,启动时先跟NameServer集群中的其中一台建立长连接,并从NameServer中获取路由信息,即当前发送的 Topic消息的Queue与 Broker的地址(IP+port)的映射关系。然后根据算法策略从队选择一个 Queue,与队列所在的 Broker建立长连接从而向 Broker发消息。当然,在获取到路由信息后,Producer会首先将路由信息缓存到本地,再每30秒从 Name server更新一次路由信息。

  5. Consumer跟 Producer类似,跟其中一台 Nameserver建立长连接,获取其所订阅 Topic的路由信息,然后根据算法策略从路由信息中获取到其所要消费的queue,然后直接跟 Broker建立长连接,开始消费其中的消息。 Consumer在获取到路由信息后,同样也会每30秒从 Name Server更新一次路由信息。不过不同于Producer的是,Consumer还会向 Broker发送心跳,以确保 Broker的存活状态。

手动Topic的创建有两种模型

1.集群模式:该模式下创建的Topic在该集群中,所有Broker中的Queue数量是相同的
2.Broker模式:该模式下创建的Topic在该集群中,每个Broker中的Queue数量可以不同

自动创建Topic时,默认采用的是Broker模式,会为每个Broker默认创建4个Queue

读写队列

从物理上来讲,读写队列是同一个队列。所以,不存在读写队列数据同步问题。读写队列是逻辑上进行区分的概念。一般情况下,读写队列数量是一样的。

例如,创建Topic时设置的写队列数量为8,读队列数量为4,此时系统会创建8个 Queue,分别是0 1 2 3 4 5 6 7。Producer会将消息写入到这8个队列,但 Consumer只会消费0 1 2 3这4个队列中的消息,4 5 6 7中的消息是不会被消费到的。

再如,创建 Topick时设置的写队列数量为4,读队列数量为8,此时系统会创建8个 Queue,分别是0 1 2 3 4 5 6 7。Producer会将消息写入到0 1 2 3这4个队列,但 Consumer只会消费0 1 2 3 4 5 6 7这8个队列中的消息,但是4567中是没有消息的。此时假设Consumer Group中包含两个Consumer,Consumer1消费0 1 2 3,而Consumer2消费4 5 6 7。但实际情况,Consumer2是没有消息可以消费。

也就是当读写队列数量不一致时,总是有问题的。其这样设计的目的是为了方便Topic的Queue的缩容。

例如,原来创建的Topic中包含16个Queue,如何能够使其Queue缩容为8个,还不会丢失消息?可以动态修改写队列数量为8,读队列数量不变。此时新的消息只能写入到前8个队列,而消费都消费的却是16个队列中的数据。当发现后8个 Queue中的消息消费完毕后,就可以再将读队列数量动态设置为8.

perm

perm用于设置对当前创建Topic的操作权限:2表示只写,4表示只读,6表示读写

posted @ 2021-12-07 15:48  Xianhao  阅读(1291)  评论(0编辑  收藏  举报