消息队列中间件(简称MQ)是指利用高效可靠的消息传递机制进行与平台无关的数据交流, 并基于数据通信来进行分布式系统的集成。通过提供消息传递和消息排队模型, 它可以在分布式环境下提供应用解耦、d性伸缩、冗余存储、流量削峰、异步通信、数据同步等等功能, 其作为分布式系统架构中的一个重要组件,有着举足轻重的地位。
RocketMQ是一套分布式消息和流处理平台, 提供了低延迟、高吞吐量、高可靠、海量堆积、灵活横向扩展能力。
1.支持常见的消息发布订阅、request/reply(同步通讯)、流式处理模型
2.金融级别的事务消息
3.可靠的FIFO队列和严格的顺序消息支持
4.高效的批量消息发送机制
5.多语言支持
6.内置的消息追踪能力
7.高性能的pull/push模型
8.海量的消息堆积能力
9.灵活的分布式横向扩展部署架构
10.支持MQ端的消息过滤机制, 包括TAG(子主题)和类SQL92表达式过滤
11.功能丰富的管理端界面,灵活的消息查询方式
12.鉴权和TLS安全访问
2.1基本架构
2.2 基本概念
- NameSrv
充当路由信息的提供者。生产者或消费者能够通过NameSrv查找各主题相应的BrokerIP列表。Broker集群
一个多个Broker组构成一个Broker集群,不同Broker组之间从实现除了集群名相同,没有过多的关联, 但建议主题创建时,以集群为单位, 从而简化运维成本,方便进行横向扩容。Broker组
多个Broker结点的集合。一个Broker组下只有一个主节点和多个从结点(可以没有从节点), 主从结点之间将会进行同步。Broker结点
负责存储消息、转发消息。其中只有主节点会存储消息。生产者Producer
是MQ场景下的一个逻辑概念,主要表示生成MQ消息并将消息发布到MQ中的角色。 一般由业务系统负责生产消息。一个消息生产者会把业务应用系统里产生的消息发送到Broker服务器。消费者Consumer
是MQ场景下的一个逻辑概念, 主要表示根据业务划分对某种类型的业务类型的消息进行订阅处理的角色. 负责消费消息,一般是后台系统负责异步消费。一个消息消费者会从Broker服务器拉取消息、并将其提供给应用程序。生产组ProducerGroup
相同类型生产者实例的集合,具有相同的组名。消费组ConsumerGroup
相同类型消费者实例的集合,具有相同的组名,同一个消费组的消费者实例的业务逻辑需要保持一至。生产者实例
是运行态的生产者,属于某个特定的生产组。消费者实例
是运行态的消费者,属于某个特定的消费组。主题
表示一类消息的集合,每个主题包含若干条消息,每条消息只能属于一个主题。标签Tag
子主题,为消息设置的标志,用于同一主题下区分不同类型的消息。 来自同一业务单元的消息,可以根据不同业务目的在同一主题下设置不同标签。 消费者可以根据Tag实现对不同子主题的不同消费逻辑,实现更好的扩展性。消息Message
消息系统所传输信息的物理载体, 生产和消费数据的最小单位,每条消息必须属于一个主题。 RocketMQ中每个消息拥有唯一的Message ID,且可以携带具有业务标识的Key。 系统提供了通过Message ID和Key查询消息的功能。队列MessageQueue
发布订阅时,消息的容器。在Broker上,消息将会存在目标主题的某个队列下。集群消费Clustering
集群消费模式下,相同Consumer Group的每个Consumer实例平均分摊消息。广播消费(Broadcasting)
广播消费模式下,相同Consumer Group的每个Consumer实例都接收全量的消息。消息回溯
回溯消费,是指Consumer已经消费成功的消息,由于业务上需求需要重新消费, 要支持此功能,Broker在向Consumer投递成功消息后,消息仍然需要保留。 并且重新消费一般是按照时间维度,例如由于Consumer系统故障, 恢复后需要重新消费1小时前的数据,那么Broker要提供一种机制,可以按照时间维度来回退消费进度。 RocketMQ支持按照时间回溯消费,时间维度精确到毫秒。
2.3 队列(MessageQueue)
对于队列的概念,在集群消费时,将会对消费者并发度限制。 在集群消费时,一般采用按照队列为单位进行分配。 如:
- 对于有一个Broker组(组名b)、读写队列数为4的主题 Test 。 最多可以有4个消费者实例实际运行。若只存在两个消费者实例,采用默认的分配策略时,每个消费者实例分配到2个队列。对于有两个Broker组(组名b, c)、读写队列数为4的主题 Test 。 最多可以有8个消费者实例实际运行。若只存在两个消费者实例,采用默认的分配策略时,每个消费者实例分配到4个队列。
有些场景下也可以启动超过4个实例(如5个实例),多于的实例用作备份实例,在实际运行的结点出现宕机时进行替换。
消费者集群模式的横向扩展性一般采用如下方式(可结合 发布订阅过程示例 理解):
- 将主题下的各个队列均摊给组内的同一消费组内的各个实例, 各个实例从分配到队列上拉取消息进行处理。如消费者处理能力不足,则可以新增单独的消费者实例进行横向扩容。同时需要注意主题读队列数限制(可根据需要进行调整),主题下队列的数量(各个Broker组读队列数之和)限制一个消费组内实际运行的消费者数量。
2.4 发布订阅过程示例
1.生产者根据请求构件消息, 将会配置主题、标签(可选)、消息头部(可选)、消息体。
2.通过NameSrv,生产者可以使用主题获取所有该主题下的队列列表
3.生产者指定或根据负载均衡自动选择队列(如 b#1 )
4.生产者将请求发送到选定队列所在的Broker组的主节点上(名为 b 的Broker组的主节点)
5.Broker主节点接收消息并存盘
6.消费组根据订阅关系,确定关注的主题(如 Test )
7.具体的消费者实例将会向NameSrv请求获取(主题 Test 的)队列列表,并向Broker获取消费者实例列表
8.消费者实例使用队列列表和实例列表进行负载均衡,分布部分队列,如实例0分配到队列 b#0
9.消费者实例从分配到的队列上拉取消息进行消费。
其中NameServer提供了Broker列表和主题列表
1.Broker会定时(registerNameServerPeriod, 默认1000 * 30ms)向NameServer发送心跳
2.NameServer会定时(10s)运行一个任务,去检查一下各个Broker的最近一次心跳时间,
3.如果某个Broker超过特定阈值(120s)都没发送心跳了,那么就认为这个Broker已经挂掉了。
4.客户端会定时(pollNameServerInterval, 默认1000 * 30ms)的通过拉取NameServer上Broker的信息。
5.其中Broker心跳、NameServer定时任务、生产者和消费者拉取Broker信息这些 *** 作都是周期性的.
我们选取了常见的几款开源的消息队列进行对比:
总的来说:
1.ActiveMQ的优势在于支持协议多样、文档资料丰富,缺点是性能、顺序投递支持有限;
2.Kafka的优势在于高吞吐率,缺点是分布式事务、消费失败重试、延时/定时消息支持有限;
3.RabbitMQ的优势在于与SpringBoot集成好,缺点是分布式事务、延时/定时消息支持有限;
4.RockeMQ的优势在于高吞吐率、顺序消息、延时消息、消息堆积、消息回溯等支持。
我们最终选择RocketMQ的主要原因如下:
1.高吞吐量、低延迟,支持高积压量。 在后端有超大规模消费者,尤其是各消费能力不均衡的前提下, 经常会出现堆积,这种影响被传递到上游生产者,进而影响交易核心业务,系统卡顿,宕机现象不在少数。 RokcetMQ在在低延迟、消息重试与追踪、海量 Topic、多租户、一致性多副本、数据可靠性等问题上进行了大量优化, 可以很好的应对金融领域的用户,更好的发挥削峰填谷、可靠性数据传输的作用。
2.RocketMQ可以严格的保证消息有序, 避免一些场景下请求的乱序处理;
3.金融服务有场景对延时消息需求, RocketMQ对于时延消息有很好的支持。消息生产和消费有时间窗口要求, 例如在电商交易中超时未支付关闭订单的场景,在订单创建时会发送一条延时消息。
4.RocketMQ在高一致性(持久化、消息重试)做的比较好;
5.为了保证最终一致性需要支持分布式事务, RocketMQ提供类似 X/Open XA 的分布事务功能,通过事务消息能达到分布式事务的最终一致。 相比其他MQ产品的事务消息,其提供的事务机制优势在于MQ内置主动查询没有提交或回滚(如提交时请求失败或其他一些异常场景)的事务消息. 同时利用消息查询可以进行进行一致性消息对账。
6.灵活的分部式可扩展部署架构,可以应对可靠性、可用性极高的场景,可以很方便的进行横向扩容。
7.完善的问题故障排查能力, 包括但不限于:
a.利用RocketMQ的消息查询功能, 可以很方便的对请求进行审查、检查和分析, 比如: 利用消息中存储的生成和存储时间等元数据进行耗时分析。
b.利用消费回溯(重置消费位点)/重新消费,支持重新消费单条/某个时间点后的消息。 例如: 由于Consumer系统故障,恢复后需要重新消费1小时前的数据
8.借助活跃的开源社区,可以快速集成多种系统
a.多语言支持,包括: GO, NodeJs等.
b.监控告警,链路追踪等系统, 如: Promethous, Skywalking,
c.借助于开源项目, 可以快速实现一些数据源的之前的同步功能;
欢迎分享,转载请注明来源:内存溢出
评论列表(0条)