RocketMQ 是什么
- 它是一个队列模型的消息中间件,具有高性能、高可靠、高实时、分布式特点
- Producer、Consumer、队列都可以分布式
- Producer 向一些队列轮流发送消息
- 队列集合称为 Topic
- Consumer 如果做广播消费
- 则一个 consumer 实例消费这个 Topic 对应的所有队列
- 如果做集群消费,则多个 Consumer 实例平均消费这个 topic 对应的队列集合
- 能够保证严格的消息顺序
- 提供丰富的消息拉叏模式
- 高效的订阅者水平扩展能力
- 实时的消息订阅机制
- 亿级消息堆积能力
- 较少的依赖
部署结构
1 ) 物理部署结构
上图是 RocketMQ 网络部署特点
- Name Server 是一个几乎无状态节点,可集群部署,节点之间无任何信息同步
- Broker 部署相对复杂
- Broker 分为 Master 与 Slave,一个 Master 可以对应多个 Slave
- 但是一个 Slave 只能对应一个 Master
- Master 与 Slave 的对应关系通过指定相同的 BrokerName
- 不同的 BrokerId 来定义 BrokerId 为 0 表示 Master,非 0 表示 Slave
- Master 也可以部署多个,每个 Broker 与 Name Server 集群中的所有节点建立长连接
- 定时注册 Topic 信息到所有 Name Server
- Producer 与 Name Server 集群中的其中一个节点(随机选择)建立长连接
- 定期从 Name Server 取 Topic 路由信息
- 并向提供 Topic 服务的 Master 建立长连接
- 且定时向 Master 发送心跳,Producer 完全无状态,可集群部署
- Consumer 与 Name Server 集群中的其中一个节点(随机选择)建立长连接
- 定期从 Name Server 取 Topic 路由信息
- 并向提供 Topic 服务的 Master、Slave 建立长连接
- 且定时向 Master、Slave 发送心跳
- Consumer 既可以从 Master 订阅消息
- 也可以从 Slave 订阅消息,订阅规则由 Broker 配置决定
2 ) 逻辑部署结构
- Producer Group
- 用来表示一个发送消息应用,一个 Producer Group 下包含多个 Producer 实例
- 可以是多台机器,也可以是一台机器的多个进程,或者一个进程的多个 Producer 对象
- 一个 Producer Group 可以发送多个 Topic消息,Producer Group 作用如下:
- 1.标识一类 Producer
- 2.可以通过运维工具查询这个发送消息应用下有多个 Producer 实例
- 3.发送分布式事务消息时,如果 Producer 中途意外宕机
- Broker 会主动回调 Producer Group 内的任意
- 一台机器来确认事务状态
- Consumer Group
- 用来表示一个消费消息应用,一个 Consumer Group 下包含多个 Consumer 实例
- 可以是多台机器,也可以是多个进程,或者是一个进程的多个 Consumer 对象
- 一个 Consumer Group 下的多个 Consumer 以均摊方式消费消息
- 如果设置为广播方式,这个 Consumer Group 下的每个实例都消费全量数据
RocketMQ 存储特点
1 )零拷贝原理
Consumer 消费消息过程,使用了零拷贝,零拷贝包含以下两种方式
1. 使用 mmap + write 方式
- 优点:即使频繁调用,使用小块文件传输,效率也很高
- 缺点:不能很好的利用 DMA 方式,会比 sendfile 多消耗 CPU,内存安全性控制复杂,需要避免 JVM Crash 问题
2. 使用 sendfile 方式
- 优点:可以利用 DMA 方式,消耗 CPU 较少,大块文件传输效率高,无内存安全新问题
- 缺点:小块文件效率低于 mmap 方式,只能是 BIO 方式传输,不能使用 NIO
RocketMQ 选择了第一种方式,mmap+write 方式,因为有小块数据传输的需求,效果会比 sendfile 更好
关于 Zero Copy 的更详细介绍,参考:https://www.linuxjournal.com/article/6345
2 )文件系统
- RocketMQ 选择 Linux Ext4 文件系统,原因如下:Ext4 文件系统删除 1G 大小的文件通常耗时小于 50ms,而 Ext3 文件系统耗时约 1s 左史,且删除文件时,磁盘IO 压力极大,会导致 IO 写入超时
- 文件系统局面需要做以下调优措施
- 文件系统 IO 调度算法需要调整为 deadline,因为 deadline 算法在随机读情况下,可以合并读请求为顺序跳跃方式,从而提高读 IO 吞吐量
- Ext4 文件系统有以下 Bug,请注意
3 )数据存储结构
4 ) 存储目录结构
|-- abort
|-- checkpoint
|-- config
| |-- consumerOffset.json
| |-- consumerOffset.json.bak
| |-- delayOffset.json
| |-- delayOffset.json.bak
| |-- subscriptionGroup.json
| |-- subscriptionGroup.json.bak
| |-- topics.json
| `-- topics.json.bak
|-- commitlog
| |-- 00000003384434229248
| |-- 00000003385507971072
| `-- 00000003386581712896
`-- consumequeue
|-- %DLQ%ConsumerGroupA
| `-- 0
| `-- 00000000000006000000
|-- %RETRY%ConsumerGroupA
| `-- 0
| `-- 00000000000000000000
|-- %RETRY%ConsumerGroupB
| `-- 0
| `-- 00000000000000000000
|-- SCHEDULE_TOPIC_XXXX
| |-- 2
| | `-- 00000000000006000000
| |-- 3
| | `-- 00000000000006000000
|-- TopicA
| |-- 0
| | |-- 00000000002604000000
| | |-- 00000000002610000000
| | `-- 00000000002616000000
| |-- 1
| | |-- 00000000002610000000
| | `-- 00000000002616000000
|-- TopicB
| |-- 0
| | `-- 00000000000732000000
| |-- 1
| | `-- 00000000000732000000
| |-- 2
| | `-- 00000000000732000000