RocketMQ简介
Rocketmq是一款分布式,队列模型的消息中间件,由阿里巴巴研发,借鉴参考了JMS规范的MQ实现,更参考了优秀的开源消息中间件KAFKA,并且结合阿里实际业务需求在天猫双十一的场景,实现业务削峰,分布式事务的优秀框架。之前git上是alibaba,现在已经转移到apache旗下,最新版本为4.3。我学习的视频的版本为alibaba3.2.6,为了适应新版本的更新,学习过程中不断参考其他新版本帖子的相关知识点
其他同类MQ产品有:Kafka,ZeroMQ,RabbitMQ,ActiveMQ等等
Git地址:https://github.com/apache/rocketmq
Rocket特性:
1. 参考了JMS规范,但有些概念与标准JMS规范不同
2. 底层通讯代码采用Netty NIO框架进行数据通信
3. .3.X版本开始摈弃了Zookeeper,内部采用更轻量级的NameServer进行网络路由,提高服务性能,天然支持消息重试机制
4. 天然支持集群模型,消费者负载均衡
5. 采用零拷贝原理,顺序写盘,支持亿级消息堆积能力
6. 提供丰富的消息机制,如顺序消息,事务消息等等
7. 提供丰富的消息拉取模式
8. 能够保证严格的消息顺序
9. 高效的订阅者水平扩展能力
10. 实时的消息订阅机制,支持广播模式
为什么选择RocketMQ
apache官方解释网址如下:
http://rocketmq.apache.org/docs/motivation/
其主要原因大概如下:
1. 强调集群无单点,可扩展,任意一点高可用,水平可扩展
2. 海量消息堆积能力,消息堆积后,写入低延迟
3. 支持上万个队列(与ActiveMQ进行对比)
4. 消息失败重试机制
5. 消息可查询
6. 开源社区活跃
7. 成熟度(经过双十一考验)
专业术语
学习RocketMQ,我们有必要了解RocketMQ的一些专业术语。他参考了JMS消息队列规范,所以有些与JMS消息队列规范相似,但却仍然有些跟JMS规范不同
Producer
消息生产者,负责产生消息,一般由业务系统负责产生消息。
Consumer
消息消费者,负责消费消息,一般是后台系统负责异步消费。
Push Consumer
Consumer 的一种,应用通常向 Consumer 对象注册一个 Listener 接口,一旦收到消息,Consumer 对象立刻回调 Listener 接口方法(JMS规范的方式)。
Pull Consumer
Consumer 的一种,应用通常主动调用 Consumer 的拉消息方法从 Broker 拉消息,主动权由应用控制。
Producer Group
一类 Producer 的集合名称,这类 Producer 通常发送一类消息,且发送逻辑一致。
Consumer Group
一类 Consumer 的集合名称,这类 Consumer 通常消费一类消息,且消费逻辑一致。
Broker
消息中转角色,它事实上就是消息队列本身,所有消息都必须通过它,由它负责存储消息,转发消息,一般也称为 Server。在 JMS 规范中称为 Provider。
广播消费
一条消息被多个 Consumer 消费,即使这些 Consumer 属于同一个 Consumer Group,消息也会被 Consumer Group 中的每个 Consumer 都消费一次,广播消费中的 Consumer Group 概念可以认为在消息划分方面无意义。
在 CORBA Notification 规范中,消费方式都属于广播消费。
在 JMS 规范中,相当于 JMS publish/subscribe model(发布/订阅模式)
集群消费
一个 Consumer Group 中的 Consumer 实例平均分摊消费消息。例如某个 Topic 有 9 条消息,其中一个Consumer Group 有 3 个实例(可能是 3 个进程,或者 3 台机器),那么每个实例只消费其中的 3 条消息。
在 CORBA Notification 规范中,无此消费方式。
在 JMS 规范中,JMS point-to-point model 与之类似,但是 RocketMQ 的集群消费功能大等亍 PTP 模型。因为RocketMQ单个Consumer Group内的消费者类似亍PTP,但是一个Topic/Queue可以被多个Consumer Group 消费。
顺序消息
消费消息的顺序要同发送消息的顺序一致,在 RocketMQ 中,主要指的是局部顺序,即一类消息为满足顺序性,必须 Producer 单线程顺序发送,且发送到同一个队列,这样 Consumer 就可以按照 Producer 发送的顺序去消费消息。
普通顺序消息
顺序消息的一种,正常情况下可以保证完全的顺序消息,但是一旦发生通信异常,Broker 重启,由于队列总数发生发化,哈希取模后定位的队列会发化,产生短暂的消息顺序不一致。
如果业务能容忍在集群异常情况(如某个 Broker 宕机戒者重启)下,消息短暂的乱序,使用普通顺序方式比较合适。
严格顺序消息
顺序消息的一种,无论正常异常情冴都能保证顺序,但是牺牲了分布式 Failover 特性,即 Broker 集群中只要有一台机器不可用,则整个集群都不可用,服务可用性大大降低。
如果服务器部署为同步双写模式,此缺陷可通过备机自动切换为主避免,不过仍然会存在几分钟的服务不可用。(依赖同步双写,主备自劢切换,自动切换功能目前还未实现)
目前已知的应用只有数据库 binlog 同步强依赖严格顺序消息,其他应用绝大部分都可以容忍短暂乱序,推荐使用普通的顺序消息。
Message Queue
在 RocketMQ 中,所有消息队列都是持久化,长度无限的数据结构,所谓长度无限是指队列中的每个存储单元都是定长,访问其中的存储单元使用 Offset 来访问,offset 为 java long 类型,64 位,理论上在 100年内不会溢出,所以认为是长度无限,另外队列中只保存最近几天的数据,之前的数据会按照过期时间来删除。
也可以认为 Message Queue 是一个长度无限的数组,offset 就是下标。
专业术语的难点解释
关于消息队列的运行结构图
①生产者生产消息,并发送消息到消息队列Broker
②消息队列Broker将消息进行本地IO存储到本地磁盘中
③消息队列Broker返回确认通知ACK包给生产者(在RocketMQ中,即返回CONSUME_SUCCESS成功标志)
以上是一种TCP短连接,即方块1的部分。RocketMQ采用Netty作为底层,是一种请求/响应的方式的连接
至于方块2,可以是短连接,也可以是长连接。
长连接的话是最常用的,即RocketMQ的Push Consumer,JMS规范中最主要的就是这种
短连接即Pull Consumer方式,采用一请求一响应的方式从本地磁盘中定时拉取消息进行消费
④ Push :消息队列Broker将信息推送给消费者进行消费,因为他们之间一直保持长连接状态,所以即时。
④ Pull:消费者定时从本地磁盘中查看是否未消费的消息。如果有,将其拉回来进行消费。保持短连接,请求响应形式。
这是关于消息队列的一个大概的原理介绍,不局限于RocketMQ,实际产品消息队列要复杂得多很多。
关于广播消费
定义如下:一条消息被多个 Consumer 消费,即使这些 Consumer 属于同一个 Consumer Group,消息也会被 Consumer Group 中的每个 Consumer 都消费一次。
这是一种发布订阅模式。但多了个Consumer Group概念需要解释一下。
只要Consumer Group 订阅了一个Topic主题,那么组下面的所有Consumer都会得到消费,所以上面的Product如果进行一条消息的生产,这条消息将会被消费五次。
关于集群消费
关于集群消费,有点类似于JMS的点对点消费模型,但又有很大的不一样。JMS的消费模型是这样的
如果生产者生产了10条消息,那么点对点的消费会是不确定的。MQ可能分配给ConsumerA9条消息,给ConsumerB1条消息。也可能给ConsumerA10条消息,一条都不给ConsumerB。这种并不能算负载均衡的措施导致程序员有时候要多做工作,比如偶数下标的给ConsumerA进行消费,奇数下标的给ConsumerB进行消费。但这种算法也是不完整的,因为一旦多添加了个Consumer的话,意味着代码需要更改,所以需要程序员下更大的功夫去进行动态的分配Consumer消费。
集群消费的定义如下:
一个 Consumer Group 中的 Consumer 实例平均分摊消费消息。例如某个 Topic 有 9 条消息,其中一个Consumer Group 有 3 个实例(可能是 3 个进程,或者 3 台机器),那么每个实例只消费其中的 3 条消息。
RocketMQ天然支持消费者负载均衡,这样每个Consumer都会消费到3条信息
因为RocketMQ单个Consumer Group内的消费者类似于PTP,但是一个Topic/Queue可以被多个Consumer Group 消费
这是在代指Consumer Group也可以像消费者一样负载均衡。
比如生产者生产了10条消息,然后存在两个Consumer Group。那么MQ会将负载均衡分给两个Group,一个5条。那么Consumer Group A会有5条消息,B也有5条。A有三个Consumer,再进行负载均衡,那么可能会是2,2,1这样进行分配消费。B有两个Consumer,那么可能是3,2这样进行分配消费。
消费者的负载均衡不仅仅局限于消费者,还有消费者的Group组。