RocketMQ
一、 专业术语
-
Producer
消息生产者,负责产生消息,一般由业务系统负责产生消息。
-
Consumer
消息消费者,负责消费消息,一般是后台系统负责异步消费。
-
PushConsumer
Consumer 的一种,应用通常向 Consumer 对象注册一个 Listener 接口,一旦收到消息,Consumer 对象立刻回调 Listener 接口方法。 -
PullConsumer
Consumer 的一种,应用通常主动调用 Consumer 的拉消息方法从 Broker 拉消息,主动权由应用控制。
-
ProducerGroup
一类 Producer 的集合名称,这类 Producer 通常发送一类消息,且发送逻辑一致。
-
ConsumerGroup
一类 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 就是下标。
二、特性
1.优先级:设置不同的topic来实现优先级,不支持严格优先级。
2.持久化:文件记录形式持久化
3.影响消息可靠性:硬件资源可立即恢复情况,能保证消息不丢,或者丢失少量数据(依赖刷盘方式是同步还是异步);不能立即恢复,单点上的消息全部丢失,通过异步复制,可保证99%的消息不丢,但是仍然会有极少量的消息可能丢失。
4.使用长轮训pull方式,可保证消息非常实时,消息实时性不低于Push。
5.每个消息必须投递一次:消费者先pull消息到本地,消费完成后,才向服务器返回ack,如果没有消费一定不会ack消息。
6.消息重复:RocketMQ不严格保证不重复,但正常情况下很少出现重复发送、消费情况。(只有网络异常、Consumer启停等异常情况下会出现消息重复)
7.Buffer:没有Buffer概念,队列都是持久化磁盘,数据定期清除。Buffer抽象成一个无限长度的队列,不管有多少数据进来都能装得下,但是会定期删除过期的数据,Broker只保存3天的消息。
8.回溯消费:支持按照时间回溯消费,时间维度精确到毫秒,可以向前回溯,也可以向后回溯。
9.消息堆积:在有slave情况下,master一旦发现Consumer访问堆积在磁盘的数据时,会向Consumer下达一个重定向指令,令Consumer从Slave拉取数据,这样正常的发消息与正常消费的Consumer都不会因为消息堆积受影响,因为系统将堆积场景与非堆积场景分割在了两个不同的节点处理。
- 消息的堆积容量:依赖磁盘大小
- 发消息的吞吐量大小受影响程度:无slave情况会受一定影响;有slave情况,不受影响。
- 正常消费的Consumer是否会受影响:无slave情况会受一定影响;有slave情况,不受影响。
- 访问堆积在磁盘的消息时,吞吐量有多大:与访问的并发有关,最慢会降到5000左右。
10.分布式事务:
11.定时消息:支持,但是不支持任意时间精度,支持特定的level,例如定时5s、10s、1m等。
12.消息重试:
13.消息过滤:
Broker端消息过滤:在Broker中按照Consumer的要求做过滤,优点是减少了对于Consumer无用消息的网络传输。缺点是增加了Broker的负担,实现相对复杂。
-
简单消息过滤:consumer.subscribe("TopicTest1", "TagA || TagC || TagD");//订阅指定topic下tags分别等于TagA或TagC或TagD
-
高级消息过滤:
Broker所在机器会启动多个FilterServer过滤进程;
Consumer启动后会向FilterServer上传一个过滤的Java类;
Consumer从FilterServer拉消息,FilterServer将请求转发给Broker,FilterServer从Broker收到消息后,按照Consumer上传的Java过滤程序做过滤,过滤完成后返回给Consumer。
Consumer端消息过滤:这种过滤方式可由应用完全自定义实现,但缺点是很多无用的消息要传输到Consumer端。
三、RocketMQ是什么
-
是一个队列模型的消息中间件,具有高性能、高可靠、高实时、分布式特点。
-
Producer、Consumer、队列都可以分布式。
-
Producer向一些队列轮流发送消息,队列集合称为Topic,Consumer如果做广播消费,则一个Consumer实例消费这个Topic对应的所有队列,如果做集群消费,则多个Consumer实例平均消费这个topic对应的队列集合。
-
能够保证严格的消息顺序。
-
提供丰富的消息拉取模式。
-
高效的订阅者水平扩展能力。
-
实时的消息订阅机制。
-
亿级消息堆积能力。
-
较少的依赖。
四、架构
1.服务发现:Name Server
专为RocketMQ设计的轻量级名称服务,具有简单、可集群横向扩展、无状态等特点。
2.逻辑部署结构
-
Producer Group
用来表示一个发送消息应用,一个Producer Group包含多个Producer实例,一个Producer Group可以发送多个Topic消息,
作用:标识一类Producer;通过运维工具查询这个发送消息应用下有多个Producer实例;发送分布式事务消息时,如果Producer中途意外宕机,Broker会主动回调Producer Group内的任意一台机器来确认事务状态。
-
Consumer Group
用来表示一个消费消息应用,一个Consumer Group下包含多个Consumer实例。一个Consumer Group下的多个Consumer以均摊方式消费消息,如果设置为广播方式,那么这个Consumer Group下的每个实例都消费全量数据。
3.物理部署结构
-
Name Server
是一个几乎无状态节点,可集群部署,节点之间无任何信息同步。
-
Broker
分为Master和Slave,一个Master可以对应多个Slave,但是一个Slave只能对应一个Master,Master与Slave的对应关系通过指定相同的BrokerName,不同的BrokerId来定义,BrokerId为0表示Master,非0表示Slave。Master也可以部署多个。每个Broker与Name Server集群中的所有节点建立长连接,定时注册Topic信息到所有NameServer。
-
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配置决定。
五、其他
1.发送消息负载均衡:轮询队列的方式发送,每个队列接收平均的消息量。
2.订阅消息负载均衡:平均。(若5个队列,2个Consumer,则第一个3个,第二个2个)(若10个队列,20个Consumer,则前10个每个一个队列,后10个Consumer不能消费消息)
3.顺序消息:将同一参数(比如OrderID)的消息发送到同一个队列。缺点:
- 发送顺序消息无法利用集群FailOver特性
- 消费顺序消息的并行度依赖于队列数量
- 队列热点问题,个别队列由于哈希不均导致消息过多,消费速度跟不上,产生消息堆积问题
- 遇到消息失败的消息,无法跳过,当前队列消费暂停