1.消息中间件的设计
- 可以先从基本的需求开始思考
- 基本的是要能支持消息的发送和接收,需要涉及到网络通信就一定会涉及到NIO
- 消息中心的消息存储(持久化/非持久化)
- 消息的序列化和反序列化
- 是否跨语言
- 消息的确认机制,如何避免消息重发
- 高级功能
- 消息的有序性
- 是否支持事务消息
- 消息收发的性能,对高并发大数据量的支持
- 是否支持集群
- 消息的可靠性存储
- 是否支持多协议
2.MQ消息存储选择
从主流的几种MQ消息队列采用的存储方式来看,主要会有三种
- 分布式KV存储,比如ActiveMQ中采用的levelDB、Redis, 这种存储方式对于消息读写能力要求不高的情况可以使用
- 文件系统存储,常见的比如kafka、RocketMQ、RabbitMQ都是采用消息刷盘到所部署的机器上的文件系统来做持久化,这种方案适合对于有高吞吐量要求的消息中间件,因为消息刷盘是一种高效率,高可靠、高性能的持久化方式,除非磁盘出现故障,否则一般是不会出现无法持久化的问题
- 关系型数据库,比如ActiveMQ可以采用mysql作为消息存储,关系型数据库在单表数据量达到千万级的情况下IO性能会出现瓶颈,所以ActiveMQ并不适合于高吞吐量的消息队列场景。
总的来说,对于存储效率,文件系统要优于分布式KV存储,分布式KV存储要优于关系型数据库
3.RocketMQ简介
RocketMq是一个由阿里巴巴开源的消息中间件, 2012年开源,2017年成为apache顶级项目。
它的核心设计借鉴了Kafka,所以我们在了解RocketMQ的时候,会发现很多和kafka相同的特性。同时,Rocket在某些功能上和kafka又有较大的差异,下面是RocketMQ的特性:
- 支持集群模型、负载均衡、水平扩展能力
- 亿级别消息堆积能力
- 采用零拷贝的原理,顺序写盘,随机读
- 底层通信框架采用Netty NIO
- NameServer代替Zookeeper,实现服务寻址和服务协调
- 消息失败重试机制、消息可查询
- 强调集群无单点,可扩展,任意一点高可用,水平可扩展
- 经过多次双十一的考验
4.RocketMQ架构
集群本身没有什么特殊之处,和kafka的整体架构类似,其中zookeeper替换成了NameServer。
在rocketmq的早版本(2.x)的时候,是没有namesrv组件的,用的是zookeeper做分布式协调和服务发现,但是后期阿里数据根据实际业务需求进行改进和优化,自组研发了轻量级的 namesrv,用于注册Client服务与Broker的请求路由工作,namesrv上不做任何消息的位置存储, 频繁操作zookeeper的位置存储数据会影响整体集群性能
RocketMQ由四部分组成:
- Name Server:提供轻量级的服务发现和路由,可集群部署,节点之间无任何信息同步。
- Broker:消息中转角色,负责存储消息转发消息,部署相对复杂。Broker 分为Master 与SlaveMaster 与Slave 的对应关系通过指定相同的BrokerName,不同的BrokerId来定义,BrokerId为0 表示Master,非0 表示Slave。一 个Master 可以对应多个Slave,但是一个Slave 只能对应一个Master。Master 也可以部署多个。
- Producer:生产者拥有相同 Producer Group 的 Producer 组成一个集群,与Name Server 集群中的其中一个节点(随机选择)建立长连接,定期从Name Server 取Topic 路由信息向提供Topic 服务的Master 建立长连接,且定时向Master 发送心跳。Producer 完全无状态,可集群部署。
- Consumer:消费者,接收消息进行消费的实例拥有相同 Consumer Group 的 Consumer 组成 一个集群与Name Server 集群中的其中一个节点(随机选择)建立长连接,定期从Name Server 取 Topic 路由信息向提供Topic 服务的Master、Slave 建立长连接,且定时向Master、Slave 发送心跳。Consumer既可以从Master 订阅消息,也可以从Slave 订阅消息,订阅规则由Broker 配置决定。
要使用rocketmq,至少需要启动两个进程,nameserver、broker,前者是各种topic注册中心,后者是真正的broker。