Apache RocketMQ™是一个开源的分布式消息和流数据平台。
1、既然是消息系统,最核心的功能就是要提供消息的发布与订阅功能,最简单的概念模型如下:
但是rocketmq提供的能力会比这个复杂的多,如一个生产方发布消息,需要多个消费方订阅,也会存在多个生产方生产消息,一个消费方消费消息,出现一对多,多对一的情况。
上图就是扩展了producer、consumer和Topic的概念模型,rocketmq最核心的概念就是Tpoic,producer和consumer都是围绕Topic展开,每个broker下可以有多个topic,topic下又可以有很对队列messageQueue,相同的topic又可以分布在不同broker节点下,producer发送消息会轮训的发送到topic的队列下;相同consumer分组是负载均衡订阅消息,不同的consumer分组之间互不干扰,即使广播订阅消息;同一Topic下的每个队列只能被相同分组下的一个consumer订阅消费,但一个consumer可以消费多个队列。
2、整体部署架构图
- nameserver是几乎没有状态的节点,可以集群部署,节点之间也没有任何数据同步。
- broker的部署相对复杂,是一个数据分散集群,分master和slave,每个master存储一部分数据,为了数据的高可用,每个master节点可以有多个slave节点,master之间无数据同步,master与slave之间有数据同步。master和slave之间的关系通过brokerName来绑定,brokerId来定义,即相同的brokerName,brokerId等于0表示master节点,非0表示slave节点。所有的broker节点与nameserver集群的所有节点保持长连接,定时注册Topic信息到所有的nameserver。
- producer与nameserver集群中的一台(随机)保持长连接,定时获取Topic路由信息,并且与提供Topic服务的broker的master节点保持长连接,并定时发送心跳,producer集群也是无状态的,可以集群部署。
- consumer与nameserver集群中的一台(随机)保持长连接,定时获取Topic路由信息,并且向提供Topic的broker的master和slave节点都保持长连接,并定时发送心跳,Consumer既可以从 Master 订阅消息,也可以从 Slave 订阅消息,订阅规则由 Broker 配置决定,consumer也是集群的部署的,负载均衡的消费Topic的消息。
3、消息的存储模型
rocketmq的消息存储与消费队列是分开的,消息被存储在commitLog下,然后再异步构建消费队列messageQueue,消费队列并不存储真正的消息内容,只是存储消息在commitLog下的偏移量、消息的长度和消息的tag的hashcode。如图所示:
- 所有数据单独存储到一个 Commit Log,完全顺序写,随机读。
- 对最终用户展现的队列实际只存储消息在 Commit Log 的位置信息,并且串行方式刷盘。
这样设计有以下优势:
- 队列轻量化,单个队列数据量非常少。
- 对磁盘的访问串行化,避免磁盘竟争,不会因为队列增加导致 IOWAIT 增高。
但也存在以下缺点:
- 写虽然完全是顺序写,但是读却变成了完全的随机读。
- 读一条消息,会先读 Consume Queue,再读 Commit Log,增加了开销。
- 要保证 Commit Log 与 Consume Queue 完全的一致,增加了编程的复杂度。
4、rocketmq具有以下特点
- 能够保证严格的消息顺序
- 提供丰富的消息拉取模式
- 高效的订阅者水平扩展能力
- 实时的消息订阅机制
- 亿级消息堆积能力
与其他消息队列系统的一个对比如下:
消息产品 | 支持客户端 | 协议和规范 | 顺序消息 | 定时消息 | 批量消息 | 广播消息 | 消息过滤 | 消息回溯 | 消息优先级 | 高可用和故障切换 | 消息追踪 | 配置 | 管理和操作工具 | Server Triggered Redelivery | 消息存储 |
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
ActiveMQ | java,c++,php,net | 推模型,支持 OpenWire, STOMP, AMQP, MQTT, JMS | 独占消费和消息分组支持顺序 | 支持 | 不支持 | 支持 | 支持 | 支持 | 支持 | 支持,leveldb+zookeeper | 不支持 | 默认配置是低级别的,用户需要优化配置参数 | 支持 | 不支持 | 支持JDBC,leveldb,kahadb |
Kafka | java,scala | 拉模型, 支持TCP | 分区内消息有顺序 | 不支持 | 支持异步生产者 | 不支持 | 支持 | 支持 | 不支持 | 支持,依赖zookeeper | 不支持 | Kafka使用键值对格式进行配置。这些值可以通过文件提供,也可以通过编程方式提供 | 支持,使用命令行 | 不支持 | 高性能文件存储 |
RocketMQ | java,c++,go | 拉模型, 支持TCP, JMS, OpenMessaging | 确保消息的严格顺序,并可以优雅地扩展 | 支持 | 支持同步模式,以避免消息丢失 | 支持 | 支持 | 支持按时间和偏移量 | 不支持 | 支持主从模式 | 支持 | 开箱即用,用户只需注意一些配置 | 支持,命令行和web客户端 | 支持 | 高性能和低延迟的文件存储 |