一、架构
RocketMQ 是阿里巴巴开源的一款分布式消息中间件。具有高性能低延时抗堆积可扩展等特点。
RocketMQ的Producer、Consumer、Broker、NameServer均支持集群化部署。
架构图如下:
二、名词解释
Broker
消息队列的服务端,消息实际存储的地方。
Master
角色为Master的Broker,一个Master + 一个Slave 分为一组,Master和Slave数据一致并保持同步关系。同步方式分为同步(sync)和异步(async)两种。
sync:好处是数据强一致,并且Master宕机,数据也不会丢。缺点是性能差。
async:好处是速度快,缺点是,假设master挂了, 未同步到Slave的数据可能丢失。
一般申请集群,共两组,四台机器,两个master,两个slave。
当一个Master挂了,数据会自动转发到另一个master上去的,即域名绑定了两个master,因此不存在leader选举问题,这也是Rocketmq使用自研的Nameserver而不使用Zookeeper的原因。
当一个Master-1挂了之后,客户端读取数据直接从Slave-1上去读取数据,写数据的时候往另一个master-2上写,master-2只会和slave-2保持同步。slave-1相当于闲置了。
待优化:服务云后期会进行优化(已经在测试),当Master挂了之后,将Slave升级为Matser,并且补一个节点充当Slave。
Slave
角色为Slave的Broker,客户端可以从Slave读取数据。
NameServer(类比 ZooKeeper )
服务发现装置,Broker注册到NameServer上,Producer和Consumer通过NameServer发现Broker的地址。
由于NameServer很轻量,一般直接和Master部署在一台机器上。
MQ
消息队列,可以看作消息传递的媒介。生产者投递到消息队列,消费者从消息队列获取消息。起到解耦和错峰的作用。
Topic
主题,每个消息都属于某个主题,一个 Topic 下可以设置多个queue(角色等同于Kafka的Partition)。
Producer
生产者,就是消息的发布方,生产者可以创建消息,并将消息源源不断地发送给消息队列。
Consumer
消费者,就是消息的订阅方,消费者可以到消息队列上订阅某个Topic,从而源源不断地获取该Topic下的消息。
Consumer Group
消费组,多个消费者组成一个组,共同来消费某个Topic,可以起到组内负载均衡的作用。
二、RocketMQ 特点
- 灵活可扩展性
RocketMQ 天然支持集群,其核心四组件(Name Server、Broker、Producer、Consumer)每一个都可以在没有单点故障的情况下进行水平扩展。 - 海量消息堆积能力
RocketMQ 采用零拷贝原理实现超大的消息的堆积能力,据说单机已可以支持亿级消息堆积,而且在堆积了这么多消息后依然保持写入低延迟。 - 支持顺序消息
可以保证消息消费者按照消息发送的顺序对消息进行消费。顺序消息分为全局有序和局部有序,一般推荐使用局部有序,即生产者通过将某一类消息按顺序发送至同一个队列来,然后消费者需要按顺序消费,即依赖MessageListenerOrderly类而不是MessageListenerConcurrently。 - 多种消息过滤方式
消息过滤分为在服务器端过滤和在消费端过滤。服务器端过滤时可以按照消息消费者的要求做过滤,优点是减少不必要消息传输,缺点是增加了消息服务器的负担,实现相对复杂。消费端过滤则完全由具体应用自定义实现,这种方式更加灵活,缺点是很多无用的消息会传输给消息消费者。 - 支持事务消息
RocketMQ 除了支持普通消息,顺序消息之外还支持事务消息,这个特性对于分布式事务来说提供了又一种解决思路。 - 回溯消费
回溯消费是指消费者已经消费成功的消息,由于业务上需求需要重新消费,RocketMQ 支持按照时间回溯消费,时间维度精确到毫秒,可以向前回溯,也可以向后回溯。
三、生产者
生产者(Producer)负责产生消息,生产者向消息服务器发送由业务应用程序系统生成的消息。 RocketMQ 提供了三种方式发送消息:同步、异步和单向。
同步发送
同步发送指消息发送方发出数据后会在收到接收方发回响应之后才发下一个数据包。一般用于重要通知消息,例如重要通知邮件、营销短信。
异步发送
异步发送指发送方发出数据后,不等接收方发回响应,接着发送下个数据包,一般用于可能链路耗时较长而对响应时间敏感的业务场景,例如用户视频上传后通知启动转码服务。
单向发送
单向发送是指只负责发送消息而不等待服务器回应且没有回调函数触发,适用于某些耗时非常短但对可靠性要求并不高的场景,例如日志收集。
生产者组
生产者组(Producer Group)是一类 Producer 的集合,这类 Producer 通常发送一类消息并且发送逻辑一致,所以将这些 Producer 分组在一起。从部署结构上看生产者通过 Producer Group 的名字来标记自己是一个集群。
四、 消费者
消费者(Consumer)负责消费消息,消费者从消息服务器拉取信息并将其输入用户应用程序。站在用户应用的角度消费者有两种类型:拉取型消费者、推送型消费者。
拉取型消费者
拉取型消费者(Pull Consumer)主动从消息服务器拉取信息,只要批量拉取到消息,用户应用就会启动消费过程,所以 Pull 称为主动消费型。
推送型消费者
推送型消费者(Push Consumer)封装了消息的拉取、消费进度和其他的内部维护工作,将消息到达时执行的回调接口留给用户应用程序来实现。所以 Push 称为被动消费类型,但从实现上看还是从消息服务器中拉取消息,不同于 Pull 的是 Push 首先要注册消费监听器,当监听器处触发后才开始消费消息。
消费者组
消费者组(Consumer Group)一类 Consumer 的集合名称,这类 Consumer 通常消费同一类消息并且消费逻辑一致,所以将这些 Consumer 分组在一起。消费者组与生产者组类似,都是将相同角色的分组在一起并命名,分组是个很精妙的概念设计,RocketMQ 正是通过这种分组机制,实现了天然的消息负载均衡。消费消息时通过 Consumer Group 实现了将消息分发到多个消费者服务器实例,比如某个 Topic 有9条消息,其中一个 Consumer Group 有3个实例(3个进程或3台机器),那么每个实例将均摊3条消息,这也意味着我们可以很方便的通过加机器来实现水平扩展。
顺序消费
消费模式分为顺序消费(Orderly)和并行消费(Concurrently)。
顺序消费:表示消息消费的顺序同生产者为每个消息队列发送的顺序一致,所以如果正在处理全局顺序是强制性的场景,需要确保使用的主题只有一个消息队列。
- 实战:拿告警消息处理举例。
- 保障同类消息推送到相同queue。根据消息的eventid得到hash值,相同hash值得发到同一个topic的同一个queue(同一个queue会有很多种eventid);
- 保障一个queue,只能有一个Consumer。方案为:假设一个topic下有48个queue,则需要48个消费者,这样就能保障一个消费者消费一个queue。也可以消费者数量少于48,6个消费者,那么每个消费者会固定消费8个queue,消费的方式是轮训消费queue,但是消费的时候会保障每个queue的顺序(这是RocketMQ自带的)
并行消费:不再保证消息顺序,消费的最大并行数量受每个消费者客户端指定的线程池限制。
五、消息服务器
消息服务器(Broker)是消息存储中心,主要作用是接收来自 Producer 的消息并存储, Consumer 从这里取得消息。它还存储与消息相关的元数据,包括用户组、消费进度偏移量、队列信息等。从部署结构图中可以看出 Broker 有 Master 和 Slave 两种类型,Master 既可以写又可以读,Slave 不可以写只可以读。从物理结构上看 Broker 的集群部署方式有四种:单 Master 、多 Master 、多 Master 多 Slave(同步刷盘)、多 Master多 Slave(异步刷盘)。
六、名称服务器
名称服务器(NameServer)用来保存 Broker 相关元信息并给 Producer 和 Consumer 查找 Broker 信息。NameServer 被设计成几乎无状态的,可以横向扩展,节点之间相互之间无通信,通过部署多台机器来标记自己是一个伪集群。每个 Broker 在启动的时候会到 NameServer 注册,Producer 在发送消息前会根据 Topic 到 NameServer 获取到 Broker 的路由信息,Consumer 也会定时获取 Topic 的路由信息。所以从功能上看应该是和 ZooKeeper 差不多,据说 RocketMQ 的早期版本确实是使用的 ZooKeeper ,后来改为了自己实现的 NameServer 。
七、消息
消息(Message)就是要传输的信息。一条消息必须有一个主题(Topic),主题可以看做是你的信件要邮寄的地址。一条消息也可以拥有一个可选的标签(Tag)和额处的键值对,它们可以用于设置一个业务 key 并在 Broker 上查找此消息以便在开发期间查找问题。
八、主题
主题(Topic)可以看做消息的规类,它是消息的第一级类型。比如一个电商系统可以分为:交易消息、物流消息等,一条消息必须有一个 Topic 。Topic 与生产者和消费者的关系非常松散,一个 Topic 可以有0个、1个、多个生产者向其发送消息,一个生产者也可以同时向不同的 Topic 发送消息。一个 Topic 也可以被 0个、1个、多个消费者订阅。
九、标签
标签(Tag)可以看作子主题,它是消息的第二级类型,用于为用户提供额外的灵活性。使用标签,同一业务模块不同目的的消息就可以用相同 Topic 而不同的 Tag 来标识。比如交易消息又可以分为:交易创建消息、交易完成消息等,一条消息可以没有 Tag 。标签有助于保持您的代码干净和连贯,并且还可以为 RocketMQ 提供的查询系统提供帮助。
十、RocketMQ 的dledger
dledger模式底层使用Raft一致性协议实现了集群的高可用和一致性。
但是集群部署对于dledger模式需要更多的服务器。
十一、RocketMQ 中,topic和queue是什么关系?消费者是如何知道与哪些queue建立连接的?
在RocketMQ中,Topic和Queue的关系是一对多的关系。一个Topic可以对应多个Queue,这样可以方便地进行分布式处理。
消费者知道与哪些Queue建立连接,主要是通过RocketMQ的消息路由信息来得知。当生产者发送消息时,会将消息发送到具体的某个Queue中,而消费者则会从RocketMQ的NameServer获取到这个Topic下所有的Queue信息,按照一定的负载均衡策略,选择其中的一个或者多个Queue进行消费。所以消费者只需要知道Topic的名称就可以了,至于这个Topic下有哪些Queue,是由RocketMQ自动进行管理的。
十二、消费者是从master还是slave节点消费消息?
在RocketMQ中,消费者消费消息既可以来自master节点,也可以来自slave节点,取决于配置和情况。
默认情况下,RocketMQ的消费者优先从master节点消费消息。但是,当master节点的压力过大,或者出现故障时,消费者会自动切换到slave节点上消费消息,以确保消息的高可用性。
RocketMQ也提供了配置项,我们可以根据需求进行设置:比如,可以设置仅从master节点消费,或者允许从slave节点消费。配置项是在消费者的Pulling的策略中进行设置的。
十三、可以同时从master和slave上消费吗?
在RocketMQ中,同一条消息的消费者不会同时从master和slave节点进行消费。
在默认情况下,消费者优先从master节点进行消费,但是当master节点不可用或者压力过大时,消费才会切换到slave节点。这是为了保证消息的可靠性和准确性,避免出现同一条消息被多次消费的情况。
同时从master和slave节点进行消费可能导致消息的重复消费,这种情况在RocketMQ中是不允许的。因此,消费者不能同时从master和slave节点进行消费。
十四、并发消费和顺序消费的原理是什么?
RocketMQ支持并发消费和顺序消费两种模式。
并发消费:RocketMQ 的并发消费是默认的消费模式。在这种模式下,消费者会从服务器拉取一批消息(一般情况下是批量拉取),然后开多个线程并发处理这些消息。这种模式的优点是处理速度快,能有效利用资源,但是可能会导致同一个队列中的消息被乱序处理。
顺序消费:RocketMQ 的顺序消费是为了保证特殊需求,即需要保证消息严格的顺序性处理。在这种模式下,消费者会一个一个地拉取并处理消息,每处理完一个消息才会去拉取下一个。因此,顺序消费的处理速度会比并发消费慢,但可以保证同一个队列中的消息按照发送的顺序被依次处理。
值得注意的是,RocketMQ 的顺序消费是在队列级别进行的,也就是说,同一个队列中的消息能够保证顺序,不同队列之间的消息顺序无法保证。
十五、RocketMQ的queue中,消息是先进先出吗?
是的,RocketMQ中的Queue是一个先进先出(FIFO)的数据结构。
RocketMQ会按照消息到达的顺序存储到Queue中,当消费者进行消费的时候,也是按照消息存入Queue的顺序进行消费,也就是说先进入Queue的消息先被消费。
但是需要注意的是,虽然RocketMQ的Queue本身保证了消息的FIFO顺序,但是如果使用并发消费模式,那么消费者处理这些消息的顺序就可能会被打乱。只有使用顺序消费模式,才能保证严格按照消息到达的顺序进行消费处理。
十六、两组broker节点的master数据是一样的吗?
两组节点的数据是不一样的,同一组的master和slave是一样的。
参考:
消息队列之 RocketMQ
RocketMQ 是如何使用dledger 模式保证故障自动恢复的