RocketMQ | 青训营笔记

75 阅读6分钟

RocketMQ

RocketMQ 是阿里开源的分布式消息中间件,跟其它中间件相比,RocketMQ 的特点是纯JAVA实现

  • 基础概念

    • Producer: 消息生产者,负责产生消息,一般由业务系统负责产生消息

    • Producer Group:消息生产者组,简单来说就是多个发送同一类消息的生产者称之为一个生产者

    • Consumer:消息消费者,负责消费消息,一般是后台系统负责异步消费

    • Consumer Group:消费者组,和生产者类似,消费同一类消息的多个 Consumer 实例组成一个消费者组

    • Topic:主题,用于将消息按主题做划分,Producer将消息发往指定的Topic,Consumer订阅该Topic就可以收到这条消息

    • Message:消息,每个message必须指定一个topic,Message 还有一个可选的 Tag 设置,以便消费端可以基于 Tag 进行过滤消息

    • Tag:标签,子主题(二级分类)对topic的进一步细化,用于区分同一个主题下的不同业务的消息

    • Broker:Broker是RocketMQ的核心模块,负责接收并存储消息,同时提供Push/Pull接口来将消息发送给Consumer。Broker同时提供消息查询的功能,可以通过MessageID和MessageKey来查询消息。Borker会将自己的Topic配置信息实时同步到NameServer

    • Queue:Topic和Queue是1对多的关系,一个Topic下可以包含多个Queue,主要用于负载均衡,Queue数量设置建议不要比消费者数少。发送消息时,用户只指定Topic,Producer会根据Topic的路由信息选择具体发到哪个Queue上。Consumer订阅消息时,会根据负载均衡策略决定订阅哪些Queue的消息

    • Offset:RocketMQ在存储消息时会为每个Topic下的每个Queue生成一个消息的索引文件,每个Queue都对应一个Offset记录当前Queue中消息条数

    • NameServer:NameServer可以看作是RocketMQ的注册中心,它管理两部分数据:集群的Topic-Queue的路由配置;Broker的实时配置信息。其它模块通过Nameserv提供的接口获取最新的Topic配置和路由信息;各 NameServer 之间不会互相通信, 各 NameServer 都有完整的路由信息,即无状态。

      • Producer/Consumer :通过查询接口获取Topic对应的Broker的地址信息和Topic-Queue的路由配置
      • Broker : 注册配置信息到NameServer, 实时更新Topic信息到NameServer
  • 消费模式

    • 广播模式:一条消息被多个Consumer消费,即使这些Consumer属于同一个Consumer Group,消息也会被Consumer Group中的每一个Consumer都消费一次。
    • 集群模式:一个Consumer Group中的所有Consumer平均分摊消费消息(组内复杂均衡)
  • 基础架构

    rocketMq使用轻量级的NameServer服务进行服务的协调和治理工作,NameServer多节点部署时相互独立互不干扰。每一个rocketMq服务节点(broker节点)启动时都会遍历配置的NameServer列表并建立长链接,broker节点每30秒向NameServer发送一次心跳信息、NameServer每10秒会检查一次连接的broker是否存活。消费者和生产者会随机选择一个NameServer建立长连接,通过定期轮训更新的方式获取最新的服务信息。

    • NameServer:启动,监听端口,等待producer,consumer,broker连接上来
    • Broker:启动,与nameserver保持长链接,定期向nameserver发送心跳信息,包含broker的ip,端口,当前broker上topic的信息
    • producer:启动,随机选择一个NameServer建立长连接,拿到broker的信息,然后就可以给broker发送消息了
    • consumer:启动,随机选择一个NameServer建立长连接,拿到broker的信息,然后就可以建立通道,消费消息
    • 存储结构

      RocketMQ 存储用的是本地文件存储系统,将所有topic的消息全部写入同一个文件中(commit log),这样保证了IO写入的绝对顺序性,最大限度利用IO系统顺序读写带来的优势提升写入速度。

        由于消息混合存储在一起,需要将每个消费者组消费topic最后的偏移量记录下来。这个文件就是consumer queue(索引文件)。所以消息在写入commit log 文件的同时还需将偏移量信息写入consumer queue文件。在索引文件中会记录消息的物理位置、偏移量offse,消息size等,消费者消费时根据上述信息就可以从commit log文件中快速找到消息信息。

  • 存储文件简介

    • Commit log:消息存储文件,rocket Mq会对commit log文件进行分割(默认大小1GB),新文件以消息最后一条消息的偏移量命名。(比如 00000000000000000000 代表了第一个文件,第二个文件名就是 00000000001073741824,表明起始偏移量为 1073741824)
    • Consumer queue:消息消费队列(也是个文件),可以根据消费者数量设置多个,一个Topic 下的某个 Queue,每个文件约 5.72M,由 30w 条数据组成;ConsumeQueue 存储的条目是固定大小,只会存储 8 字节的 commitlog 物理偏移量,4 字节的消息长度和 8 字节 Tag 的哈希值,固定 20 字节;消费者是先从 ConsumeQueue 来得到消息真实的物理地址,然后再去 CommitLog 获取消息
    • IndexFile:索引文件,是额外提供查找消息的手段,通过 Key 或者时间区间来查询对应的消息
  • 整个流程简介:

    • Producer 使用轮询的方式分别向每个 Queue 中发送消息
    • Consumer 启动的时候会在 Topic,Consumer group 维度发生负载均衡,为每个客户端分配需要处理的 Queue。负载均衡过程中每个客户端都获取到全部的的 ConsumerID 和所有 Queue 并进行排序,每个客户端使用相同负责均衡算法,例如平均分配的算法,这样每个客户端都会计算出自己需要消费那些 Queue,每当 Consumer 增加或减少就会触发负载均衡,所以我们可以通过 RocketMQ 负载均衡机制实现动态扩容,提升客户端收发消息能力。客户端负责均衡为客户端分配好 Queue 后,客户端会不断向 Broker 拉取消息,在客户端进行消费。
  • Consumer 端的负载均衡机制   topic 在创建之处可以设置 comsumer queue数量。而 comsumer 在启动时会和comsumer queue绑定

  • 默认策略

    • queue 个数大于 Consumer个数, 那么 Consumer 会平均分配 queue,不够平均,会根据clientId排序来拿取余数
    • queue个数小于Consumer个数,那么会有Consumer闲置,就是浪费掉了,其余Consumer平均分配到queue
  • 消息刷盘机制

    • 同步刷盘:当消息持久化完成后,Broker才会返回给Producer一个ACK响应,可以保证消息的可靠性,但是性能较低。
    • 异步刷盘:只要消息写入PageCache即可将成功的ACK返回给Producer端。消息刷盘采用后台异步线程提交的方式进行,降低了读写延迟,提高了RocketMQ的性能和吞吐量。

具体可以参考 RocketMQ 详解_罗志宏的博客-CSDN博客