RocketMQ
领域模型
消息生产
- 生产者(Producer):
Apache RocketMQ 中用于产生消息的运行实体,一般集成于业务调用链路的上游。生产者是轻量级匿名无身份的。
消息存储
- 主题(Topic):
Apache RocketMQ 消息传输和存储的分组容器,主题内部由多个队列组成,消息的存储和水平扩展实际是通过主题内的队列实现的。
- 队列(MessageQueue):
Apache RocketMQ 消息传输和存储的实际单元容器,类比于其他消息队列中的分区。 Apache RocketMQ 通过流式特性的无限队列结构来存储消息,消息在队列内具备顺序性存储特征。
- 消息(Message):
Apache RocketMQ 的最小传输单元。消息具备不可变性,在初始化发送和完成存储后即不可变。
消息消费
- 消费者分组(ConsumerGroup):
Apache RocketMQ 发布订阅模型中定义的独立的消费身份分组,用于统一管理底层运行的多个消费者(Consumer)。同一个消费组的多个消费者必须保持消费逻辑和配置一致,共同分担该消费组订阅的消息,实现消费能力的水平扩展。
- 消费者(Consumer):
Apache RocketMQ 消费消息的运行实体,一般集成在业务调用链路的下游。消费者必须被指定到某一个消费组中。
- 订阅关系(Subscription):
Apache RocketMQ 发布订阅模型中消息过滤、重试、消费进度的规则配置。订阅关系以消费组粒度进行管理,消费组通过定义订阅关系控制指定消费组下的消费者如何实现消息过滤、消费重试及消费进度恢复等。 Apache RocketMQ 的订阅关系除过滤表达式之外都是持久化的,即服务端重启或请求断开,订阅关系依然保留。
消息存储的存储结构
消息存储架构图中主要有下面三个跟消息存储相关的文件构成
- CommitLog
消息主体以及元数据的存储主体,存储Producer端写入的消息主体内容,消息内容不是定长的。\ 单个文件大小默认1G ,文件名长度为20位,左边补零,剩余为起始偏移量,\ 比如00000000000000000000代表了第一个文件,起始偏移量为0,文件大小为1G=1073741824;当第一个文件写满了,第二个文件为00000000001073741824,起始偏移量为1073741824,以此类推。消息主要是顺序写入日志文件,当文件满了,写入下一个文件;
- ConsumeQueue(逻辑消费队列)
消息消费队列,引入的目的主要是提高消息消费的性能 \ 保存了指定Topic下的队列消息在CommitLog中的起始物理偏移量offset,消息大小size和消息Tag的HashCode值,\ 定长设计,每个条目20字节(8字节的commitlog物理偏移量、4字节的消息长度、8字节tag hashcod),单个文件由30W个条目组成,可以像数组一样随机访问每一个条目\
- IndexFile
提供了一种可以通过key或时间区间来查询消息的方法 \ IndexFile的底层存储设计为在文件系统中实现HashMap结构,故rocketmq的索引文件其底层实现为hash索引
三个文件的关系
Broker单个实例下所有的队列共用一个日志数据文件(即为CommitLog)来存储 Producer发送消息至Broker端,然后Broker端使用同步或者异步的方式对消息刷盘持久化,保存至CommitLog中. 然后,ReputMessageService不停地分发请求并异步构建ConsumeQueue(逻辑消费队列)和IndexFile(索引文件)数据。
rocketmq 针对读写的优化
- 页缓存(PageCache)
- ConsumeQueue逻辑消费队列存储的数据较少,并且是顺序读取
- 零拷贝技术:利用MappedByteBuffer对文件进行读写操作。其中,利用了NIO中的FileChannel模型将磁盘上的物理文件直接映射到用户态的内存地址中
部署架构
主要角色介绍
- Producer
- Consumer
- NameServer
NameServer是一个非常简单的Topic路由注册中心,主要包括两个功能:\
- NameServer接受Broker集群的注册信息并且保存下来作为路由信息的基本数据。
- 提供心跳检测机制,检查Broker是否还存活 NameServer通常也是集群的方式部署,各实例间相互不进行信息通讯。Broker是向每一台NameServer注册自己的路由信息
- BrokerServer
主要负责消息的存储、投递和查询以及服务高可用保证,主要包含以下几个子模块
- Remoting Module:整个Broker的实体,负责处理来自clients端的请求。
- Client Manager:负责管理客户端(Producer/Consumer)和维护Consumer的Topic订阅信息
- Store Service:提供方便简单的API接口处理消息存储到物理硬盘和查询功能。
- HA Service:高可用服务,提供Master Broker 和 Slave Broker之间的数据同步功能。
- Index Service:根据特定的Message key对投递到Broker的消息进行索引服务,以提供消息的快速查询。
消息消费模式
- Push & pull
- push 基于长轮训
- pull 消费者主动拉取 Push / Pull 消费模式的负载均衡是在客户端完成的,性能较高,但也有一些缺陷。
- 客户端代码逻辑复杂,客户端要实现完整的负载均衡,拉消息,位点管理,消费失败后将消息发回 Broker 重试等逻辑。这给多语言客户端的支持造成很大的阻碍。
- 消费者无法无限扩展,当消费者数量扩大到大于队列数量时,有的消费者将无法分配到队列。
- 当某些消费者僵死(hang 住)时,会造成其消费的队列的消息堆积。
- pop 消费
- RocketMQ 5.0 开始支持
- 核心在于将重平衡、位点管理及消息重试等任务转移至服务端处理.有效避免单点故障引起的消息积压,优化了整体消息处理效率和系统的水平扩展能力。
功能特性
定时、延时消息
事务消息
顺序消息
支持消费者按照发送消息的先后顺序获取消息,从而实现业务场景中的顺序处理。相比其他类型消息,顺序消息在发送、存储和投递的处理过程中,更多强调多条消息间的先后顺序关系。 Apache RocketMQ 顺序消息的顺序关系通过消息组(MessageGroup)判定和识别
如何保证消息的顺序性
- 生产顺序性
- 消息生产的顺序性仅支持单一生产者
- 串行发送,不能多线程发
- 顺序存储
- 相同消息组的消息按照先后顺序被存储在同一个队列。
- 不同消息组的消息可以混合在同一个队列中,且不保证连续。
- 消费顺序性
- 投递顺序
- 有限重试