1.介绍
对于即时通讯,所有技术文章和材料都是围绕即时通讯的技术方向组织和共享的,这次也不例外。对于即时通讯系统(包括即时消息、消息推送系统等。),MQ消息中间件是一个非常常见的基础软件,但是市场上有很多种MQ消息中间件产品,那么如何选择它们呢?这是个问题!
对于许多没有经验的开发人员来说,一个公司的内部即时消息聊天系统只有一百个用户,比如卡夫卡和蒙古数据库,它们被称为“高性能和可扩展性”。对于中型和大型即时通讯场景,一些开发人员使用臃肿的ActiveMQ,而不是贪婪于简单的使用和全面的数据,这有点混乱。
综上所述,应该使用什么样的场景,哪些MQ消息中间件产品是合适的?读完这篇文章,你可能会有答案。
本文将从17个维度对目前最流行的MQ消息中间件产品Kafka、RabbitMQ、ZeroMQ、RocketMQ和ActiveMQ进行全面的比较,希望能为您下一步的产品架构设计和MQ消息中间件的选择提供参考。
多维比较五个主流分布式MQ消息队列,我妈妈不再担心我的技术选择_ untitled-1.jpg。
2.有关数据
官方网站地址:
卡夫卡:http://kafka.apache.org/
拉比:https://www.rabbitmq.com/
http://zeromq.org/
火箭:http://rocketmq.apache.org/
http://activemq.apache.org/
相关文章:
构成即时消息开发的基础知识(5):易于理解、正确理解并充分利用MQ消息队列
即时消息系统中MQ消息中间件的类型选择:卡夫卡还是拉比?》
3.维度1:数据文档
1)卡夫卡:数据量中等。有卡夫卡作者写的书和一些在线材料。
拉比:有很多数据。有一些好书,也有许多在线材料。
3)零MQ:数据量很小。很少有专门写ZeroMQ的书,在线资料主要是一些代码的实现和简介。
4)火箭MQ:数据量很小。目前有两本书专门介绍RocketMQ互联网上的信息是混杂的,官方文件是简洁的,但没有太多的技术细节的描述。
5)活动:有很多数据。没有专门针对ActiveMQ的书籍,也有许多在线材料。
4.维度2:发展语言
1)卡夫卡:斯卡拉
2)RabbitMQ:Erlang
3)零MQ: C语言
4)火箭:Java
5)主动队列:Java
5.维度3:支持的协议
1)卡夫卡:一组自定义…(基于TCP)
2)拉比:AMQP
3)零MQ:TCP、UDP
4)RockemQ:一组自定义的…
5)主动MQ:OpenWire、STOMP、REST、XMPP、AMQP
6.维度4:消息存储
1)卡夫卡:
内存,磁盘,数据库。支持大规模积累。
卡夫卡最小的存储单元是分区,一个主题包含多个分区。当卡夫卡创建一个主题时,这些分区将分布在多个服务器上,通常是一个代理和一个服务器。
分区领导将均匀分布在不同的服务器上,分区副本也将均匀分布在不同的服务器上,以确保负载平衡和高可用性。当新的代理加入集群时,一些副本将被移动到新的代理。
根据配置文件中的目录列表,Kafka会将新分区分配给目录列表中分区数量最少的目录。
默认情况下,分区使用轮询算法在同一主题的不同分区中平均分配消息。如果发送时指定了密钥,将根据密钥的hashcode的模值存储在相应的分区中。
2)拉比:
内存,磁盘。支持少量堆叠。
拉比消息分为持久消息和非持久消息,持久消息和非持久消息都可以写入磁盘。
持久消息到达队列时会写入磁盘,如果可能,持久消息还会作为备份保存在内存中,这可以提高某些性能,并且在内存紧张时会从内存中清除。
非持久消息一般只存在于内存中,当内存紧张时会被替换到磁盘上,以节省内存。
通过引入镜像队列机制,重要队列可以被“复制”到集群中的其他代理,并且这些队列的消息不会丢失。
配置用于镜像的队列都包含一个主节点和多个从节点。如果主机失败,加入时间最长的从机将被提升为新的主机,除发送消息外的所有动作都将发送给主机,然后主机将命令执行结果广播给所有从机。RabbitMQ将使主机平均分布在不同的服务器上,而同一队列中的从机将平均分布在不同的服务器上,确保负载平衡和高可用性。
3)零MQ:
消息发送者的内存或磁盘。不支持持久性。
4)RockemQ:
磁盘。支持大规模积累。
CommitLog文件存储实际的消息数据,每个commitLog的上限是1G。当它已满时,将自动创建一个新的commitLog文件来保存数据。
ConsumeQueue队列只存储偏移量、大小和标记代码,它们非常小,分布在多个代理上。
ConsumeQueue相当于CommitLog的索引文件。当消费者消费时,他们将在commitLog中查找来自消费者的消息的偏移量,然后在commitLog中查找元数据。
消费存储格式的特性确保了写入过程是按顺序执行的(写入CommitLog文件)。大量数据IO按顺序写入同一个commitLog,新的IO在1G后写入。
此外,在积累了4K之后,RocketMQ被迫从页面缓存刷到磁盘(缓存),因此高并发写入性能是突出的。
5)主动队列:
内存,磁盘,数据库。支持少量堆叠。
7.维度5:消息事务
1)卡夫卡:支持
2)支持。客户端将通道设置为事务模式,只有当消息被RabbitMQ接收到时,事务才能被成功提交,否则,在捕获到异常后,它将被回滚。使用事务会降低性能
3)零MQ:不支持
4)火箭:支持
5)活动质量:支持
8.维度6:负载平衡
8.1卡法卡
支持负载平衡。
1)代理通常是服务器节点。
对于同一主题的不同分区,卡夫卡会尽最大努力将这些分区分配给不同的代理服务器。zookeeper保存代理、主题和分区的元数据信息。
分区领导将处理来自客户端的生产请求,而卡夫卡分区领导将被分配到不同的代理服务器来共享任务。
每个代理缓存元数据信息,客户端可以从任何代理获取元数据信息并缓存,根据元数据信息知道向哪里发送请求。
2)卡夫卡的消费者群体认同相同的主题,这将使每个消费者分配相同数量的分区,并尽可能地分担负载。
3)当消费者加入或退出消费者组时,它还会触发重新平衡、重新分配分区以及为每个消费者共享负载。
卡夫卡的大部分负载平衡都是自动完成的,分区的创建也是由卡夫卡完成的,这隐藏了许多细节,避免了繁琐的配置和人为疏忽所导致的负载问题。
4)主题和密钥决定消息被发送到哪个分区。如果关键字为空,将使用轮询算法将消息发送到同一主题的不同分区。如果键不为空,将根据hashcode模键计算要发送到的分区。
8.2RabbitMQ
不支持负载平衡。
1)消息传送到哪个队列由交换机和密钥决定,交换机、路由密钥和队列都需要手动创建。
为了与代理建立连接,RabbitMQ客户端需要提前知道代理上有哪些交换机和队列。
通常,有必要声明要发送的目标队列。如果没有目标队列,将在代理上创建一个队列。如果有,将不处理任何内容,然后消息将被发送到该队列。假设大部分繁重任务的队列是在同一个代理上创建的,那么这个代理的负载将会太大。
您可以在联机之前预先创建一个队列,而无需声明要发送的队列。但是,在发送时,您不会尝试创建队列,可能会出现找不到队列的问题。RabbitMQ的备份开关会将找不到队列的消息保存到一个特殊的队列中,以便将来查询。
利用镜像队列机制建立RabbitMQ集群可以解决这一问题,形成主从架构。主节点将平均分布在不同的服务器上,这样每个服务器可以分担负载。从节点只负责转发,当主节点失败时,它会选择加入时间最长的从节点成为主节点。
当新节点加入镜像队列时,除非调用同步命令,否则队列中的消息不会同步到新的从属节点,但在调用该命令后,队列将被阻止,并且无法在生产环境中调用同步命令。
2)当拉比队列有多个消费者时,队列接收的消息将通过轮询分配发送给消费者。每个消息将只发送给订阅列表中的一个消费者,不会重复。
这种方法非常适合扩展,是专门为并发程序设计的。
如果一些消费者有繁重的任务,您可以设置基本服务质量来限制消费者可以保留在信道上的未确认消息的最大数量。当达到上限时,RabbitMQ将不再向该消费者发送任何消息。
3)对于RabbitMQ,客户端和集群之间的TCP连接不是建立与集群中所有节点的连接,而是选择一个节点建立连接。
然而,RabbitMQ集群可以在客户端通过HAProxy、LVS技术或算法来实现负载均衡。引入负载平衡后,每个客户端的连接可以分布到集群的每个节点。
客户端平衡算法:
A.轮询方法:依次返回下一个服务器的连接地址。
B.加权轮询方法:为高配置、低负载的机器分配更高的权重,让它们处理更多的请求;然而,低配置和高负载的机器被分配较低的重量以减少它们的系统负载。
C.随机方法:随机选择服务器的连接地址。
d加权随机法:根据概率随机选择连接地址。
E.源地址散列法:由散列函数计算的数值,用于对服务器列表的大小进行模运算。
F.最小连接方法:动态选择当前连接数最少的服务器的连接地址。
8.3零MQ
分散化不支持负载平衡。它只是一个多线程网络库。
8.4时钟
支持负载平衡。
代理通常是服务器节点。经纪人分为主人和奴隶。主机和从机存储相同的数据,从机同步来自主机的数据。
1)名称服务器与每个集群成员保持心跳,并保持主题代理的路由信息。同一主题的队列将分布在不同的服务器上。
2)通过轮询队列发送消息,每个队列接收平均消息数量。主题、标签和密钥是为发送消息而指定的,但是不可能指定要发送到哪个队列(没有意义,集群消耗和广播消耗与消息存储在哪个队列无关)。
标签是可选的,类似于Gmail为每封邮件设置的标签,便于服务器过滤和使用。目前,每个消息只设置了一个标签,因此可以将其类比为通知的消息类型的概念。
关键字是可选的,它表示此消息的业务关键字。服务器将根据密钥创建一个散列索引。设置后,您可以在控制台系统中根据主题和键查询消息。由于这是一个哈希索引,请确保密钥尽可能唯一,如订单号和商品标识。
3)RockemQ的负载平衡策略规定:
消费者的数量应该小于或等于队列的数量。如果使用者的数量超过了队列的数量,多余的使用者将不能使用消息。
这与卡夫卡是一致的。RocketMQ将尽可能多地为每个消费者分配相同数量的队列来分担负载。
8.5活动MQ
支持负载平衡。基于zookeeper可以实现负载均衡。
9.维度7:集群模式
1)卡夫卡:
自然的“主从”无状态集群,每台服务器既是主机又是从机。
分区领导均匀分布在不同的卡夫卡服务器上,分区副本也均匀分布在不同的卡夫卡服务器上,因此每个卡夫卡服务器都包含分区领导和分区副本。
每个卡夫卡服务器都是某个卡夫卡服务器的奴隶和某个卡夫卡服务器的领导者。
卡夫卡的集群依赖于支持热扩张的动物园管理员。所有代理、消费者和分区都可以在不关闭服务的情况下动态添加和删除。与不依赖动物园管理员集群的mq相比,这是最大的优势。
2)拉比:
支持简单群集、“复制”模式,但不支持高级群集模式。
无论是单节点系统还是集群的一部分,每个节点都是内存节点或磁盘节点,集群中至少有一个节点必须是磁盘节点。
在RabbitMQ集群中创建队列时,集群将仅在单个节点上创建队列进程并完成队列信息(元数据、状态和内容),而不是在所有节点上。
镜像队列的引入可以避免单点故障并确保服务的可用性,但是有必要为一些重要的队列手动配置镜像。
3)零MQ:
分散化不支持集群。
4)RockemQ:
通常使用多对多“主从”模式,开源版本需要手动将从机切换到主机。
名称服务器是一个几乎无状态的节点,它可以部署在集群中,节点之间没有任何信息同步。
代理部署相对复杂。经纪人分为主人和奴隶。一个主机可以对应多个从机,但一个从机只能对应一个主机。
通过指定相同的代理名称和不同的代理标识来定义主机和从机之间的关系,其中代理标识对于主机为0,对于从机为非0。
Master还可以部署多个。每个代理与名称服务器群集中的所有节点建立长连接,并定期向所有名称服务器注册主题信息。
生产者与名称服务器群集中的一个节点(随机选择)建立长连接,定期从名称服务器获取主题路由信息,与提供主题服务的主服务器建立长连接,并定期向主服务器发送心跳。生产者是完全无状态的,可以部署在集群中。
消费者与名称服务器群集中的一个节点(随机选择)建立长连接,定期从名称服务器获取主题路由信息,与提供主题服务的主服务器和从服务器建立长连接,并定期向主服务器和从服务器发送心跳信号。
消费者可以订阅来自主机或从机的消息,订阅规则由代理配置决定。
客户端首先找到名称服务器,然后通过名称服务器找到代理。
一个主题有多个队列,这些队列平均分布在不同的代理服务器上。火箭队列的概念与卡夫卡的分区概念基本一致。卡夫卡同一主题的分区尽可能分布在不同的代理上,分区副本也分布在不同的代理上。
RocketMQ集群的从设备从主设备获取数据备份,主设备分布在不同的代理上。
5)主动队列:
支持简单集群模式,如“主备”,但不支持高级集群模式。
10.维度8:管理界面
1)卡夫卡:一般
2)拉比问:好的
3)零MQ:无
4)火箭问:有一个管理背景,但它不是在项目中建立的。您需要自己启动一个单独的管理后台实例
5)ActiveMQ:常规
11.维度9:可用性
1)卡夫卡:非常高(分布式)
2)拉比tMQ:高(主从)
3)零MQ:高
4)火箭MQ:非常高(分布式)
5)主动MQ:高(主从)
12.维度10:重复的消息
1)卡夫卡:至少支持一次,最多支持一次
2)支持至少一次,最多一次
3)零MQ:只有重传机制,但是没有持久性,如果消息丢失了,重传是没有用的。它既不是至少一次,也不是最多一次,也不是仅仅一次
4)火箭MQ:支持至少一次
5)活动MQ:支持至少一次
13.维度11:吞吐量TPS
1)卡夫卡:最大。卡夫卡分批发送消息和消费消息。发送者合并几条小消息,并分批将其发送给代理,而消费者取出一批消息进行批处理。
2)拉比:相对较大
3)零MQ:最大值
4)RockemQ:大。RocketMQ的接收者可以成批使用消息,并配置每次使用的消息数量,但是发送者不成批发送消息。
5)活动MQ:相对较大
14.维度12:订阅表单和消息分发
14.1卡法卡
基于主题的发布-订阅模式和基于主题的规则匹配。
1)发送:
在发送方,主题和密钥决定了将消息发送到哪个分区。如果关键字为空,将使用轮询算法向同一主题的不同分区发送消息。如果键不为空,将根据hashcode模键计算要发送到的分区。
2)接收:
消费者向组协调器代理发送心跳信号,以维护他们与组的从属关系以及他们与分区的所有权关系。一旦所有权关系被分配,它将不会改变。除非发生重新平衡(例如,消费者加入或离开消费者组),否则消费者将只读取来自相应分区的消息。
卡夫卡将消费者的数量限制为少于分区的数量,并且每个消息将只由同一消费者组的一个消费者消费(不广播)。
当卡夫卡的消费者组订阅相同的主题时,每个消费者将被尽可能多地分配到相同数量的分区。不同的消费群体独立订阅同一主题,同一消息将由不同的消费群体处理。
14.2RabbitMQ
有四种:直接、主题、标题和扇出。
1)发送:
首先,声明一个将要创建或已经创建的队列,该队列是基本的存储单元。
交换和密钥决定了队列消息存储在哪个队列中。
直接>被发送到与绑定键完全匹配的队列。
主题>路由关键字是一个包含“.”的字符串,它将被发送到包含“*”和“#”的bingKey对应的队列进行模糊匹配。
扇出>与密钥无关,将被发送到所有绑定到交换的队列
标题>与键无关。当消息内容的headers属性(键值对)完全匹配绑定键值对时,它将被发送到这个队列。这种方法性能低,通常不使用
2)接收:
拉比队列是基本的存储单元,不再进行分区或分段。对于我们创建的队列,消费者应该指定从哪个队列接收消息。
当拉比队列有多个消费者时,队列接收的消息将通过轮询分配发送给消费者。每个消息将只发送给订阅列表中的一个消费者,不会重复。
这种方法非常适合扩展,是专门为并发程序设计的。
如果一些消费者有繁重的任务,您可以设置基本服务质量来限制消费者可以保留在信道上的未确认消息的最大数量。当达到上限时,RabbitMQ将不再向该消费者发送任何消息。
14.3零MQ
点对点(p2p)。
14.4RocketMQ
发布-订阅模式基于主题/消息标签,并根据消息类型和属性进行定期匹配。
1)发送:
发送消息由轮询队列发送,每个队列接收一个平均消息量。主题、标签和密钥是为发送消息而指定的,但是不可能指定要发送到哪个队列(没有意义,集群消耗和广播消耗与消息存储在哪个队列无关)。
标签是可选的,类似于Gmail为每封邮件设置的标签,便于服务器过滤和使用。目前,每个消息只设置了一个标签,因此可以将其类比为通知的消息类型的概念。
关键字是可选的,它表示此消息的业务关键字。服务器将根据密钥创建一个散列索引。设置后,您可以在控制台系统中根据主题和键查询消息。由于这是一个哈希索引,请确保密钥尽可能唯一,如订单号和商品标识。
2)接收:
广播消费。一条消息由多个使用者使用,即使这些使用者属于同一个使用者组,该消息也将由使用者组中的每个使用者使用一次。
集群消费。消费者组中的消费者实例平等地共享消费消息。例如,如果一个主题有9条消息,而一个使用者组有3个实例,则每个实例仅使用3条消息。也就是说,每个队列依次向每个消费者分发消息。
14.5活动MQ
点对点(p2p)、广播(发布-订阅)。
对等模式下,每条消息只有一个消费者;发布/订阅模式,每个消息可以有多个消费者。
1)发送:
对等模式:首先指定一个队列,该队列将被创建或已经被创建。
发布/订阅模式:首先指定一个将要创建或已经创建的主题。
2)接收:
对等模式:对于已经创建的队列,使用者应该指定从哪个队列接收消息。
发布/订阅模式:对于创建的主题,消费者应该指定订阅哪个主题。
15.维度13:顺序消息
卡夫卡:支持。
将生产者的最大in.flight.requests.per .连接设置为1可以确保消息按发送顺序写入服务器,即使重试也是如此。
卡夫卡保证同一分区中的信息是有序的,但有两种情况是这样的:
(1)①键为空,消息被一个接一个地写入不同主机的分区中,但是对于每个分区来说它们仍然是有序的
②②键不为空,消息被写入同一个分区,该分区的消息都是有序的。
RabbitMQ:不支持
零MQ:不支持
火箭MQ:支持
ActiveMQ:不支持
16.维度14:消息确认
16.1卡法卡
支持。
1)发送者确认机制:
Ack=0,无论消息是否成功写入分区。
Ack=1,消息成功写入前导分区后,返回成功
Ack=all,当消息成功写入所有分区时,返回成功。
2)收件人确认机制:
自动或手动提交分区偏移,早期版本的卡夫卡偏移提交给动物园管理员,这使得动物园管理员承受更大的压力。Kafka偏移的更新版本提交给Kafka服务器,不再依赖Zookeeper组,集群性能更加稳定。
16.2RabbitMQ
支持。
1)发送者确认机制,在消息被传递到所有匹配的队列之后,它返回成功。如果消息和队列是持久的,它们将在写入磁盘后返回成功。支持批量确认和异步确认。
2)接收方确认机制:设置自动确认为假,需要明确确认;设置自动确认为真,自动确认。
当自动确认为假时,拉比队列将分为两部分,一部分是等待发送给消费者的消息,另一部分是已经发送但没有收到确认的消息。
如果没有收到确认信号,并且消费者已经断开连接,RabbitMQ将安排该消息重新进入队列,并将其传递给原始消费者或下一个消费者。
未确认的邮件没有过期时间。如果它们没有被确认并且没有被断开连接,则rabbtmq将一直等待,并且rabbtmq允许消息被处理很长时间。
16.3零MQ
支持。
16.4RocketMQ
支持。
16.5活动MQ
支持。
17.维度15:消息回溯
1)卡夫卡:支持指定分区偏移位置的回溯
2)拉比问:不支持
3)零MQ:不支持
4)火箭MQ:支持在指定时间点回溯
5)活动MQ:不支持
18.维度16:消息重试
18.1卡法卡
它不受支持,但可以实现。
卡夫卡支持回溯指定分区的偏移位置,可以实现消息重试。
18.2RabbitMQ
它不受支持,但可以通过消息确认机制实现。
接收方确认机制将自动检查设置为假。
当自动确认为假时,拉比队列将分为两部分,一部分是等待发送给消费者的消息,另一部分是已经发送但没有收到确认的消息。
如果没有收到确认信号,并且消费者已经断开连接,RabbitMQ将安排该消息重新进入队列,并将其传递给原始消费者或下一个消费者。
18.3零MQ
不支持。
18.4RocketMQ
支持
在大多数消息消费失败的情况下,99%的重试会立即失败,因此RocketMQ的策略是在消费失败时定期重试,每次重试的时间间隔相同。
1)发送方自身的发送方法支持内部重试,重试逻辑如下:
最多重试3次;
如果发送失败,转向下一个经纪人;;
此方法花费的总时间不超过sendMsgTimeout设置的值,默认情况下该值为10秒。如果超过时间,请重试。
2)接收端:
在消费者未能消费该消息之后,应该提供重试机制以使该消息再次消费。消费者未能消费信息通常可分为以下两种情况:
由于消息本身,如反序列化失败,消息数据本身无法处理(例如,电话账单被充值,当前消息的手机号码被取消,无法充值)。定时重试机制,如10秒后重试。
由于依赖的下游应用服务不可用,例如不可用的数据库连接和不可达的外部系统网络。即使跳过当前失败的消息,使用其他消息也会报告错误。在这种情况下,您可以休眠30秒,然后使用下一条消息,从而减轻代理重试该消息的压力。
18.5活动MQ
不支持
19.维度17:并发
19.1卡法卡
并发性很高。
一条线是消费者。卡夫卡将消费者的数量限制为小于或等于分区的数量。如果您想提高并行性,可以在消费者之间启动多线程,或者增加消费者实例的数量。
19.2RabbitMQ
并发性极高。它用Erlang语言编写,具有高并发性。
多线程可以在消费者中启动。最常见的方法是一个通道对应一个消费者,每个线程拥有一个通道,多个线程重用连接的tcp连接来降低性能开销。
当拉比队列有多个消费者时,队列接收的消息将通过轮询分配发送给消费者。每个消息将只发送给订阅列表中的一个消费者,不会重复。
这种方法非常适合扩展,是专门为并发程序设计的。
如果一些消费者有繁重的任务,您可以设置基本服务质量来限制消费者可以保留在信道上的未确认消息的最大数量。当达到上限时,RabbitMQ将不再向该消费者发送任何消息。
19.3零MQ
并发性很高。
19.4RocketMQ
并发性很高。
1)RockemQ将消费者的数量限制为小于或等于队列的数量,但是它可以在消费者之间启动多线程,这与Kafka是一致的,并且提高并行性的方法是相同的。
修改消耗并行度的方法:
在相同的使用者组下,通过增加使用者实例的数量来提高并行性,并且超过订阅队列数量的使用者实例是无效的。
通过修改参数consumeThreadMin和consumeThreadMax,改进单个消费者的消费并行线程
2)当同一网络连接到连接时,客户端的多个线程可以同时发送请求,并且连接将被重用,从而降低性能开销。
19.5活动MQ
并发性很高。
单个ActiveMQ的消息接收和使用速度为10,000/s(持久性一般为10,000-20,000,非持久性超过20,000),在生产环境中部署10个ActiveMQ可以实现超过100,000/s的性能。部署的活动MQ代理越多,MQ的延迟就越低,系统吞吐量就越高。
----------------------------------------------------------------------------------
哇谷im_im即时通讯_私有云_公有云-哇谷云科技官网-JM沟通
IM下载体验 - 哇谷IM-企业云办公IM即时聊天社交系统-JM 沟通下载
IM功能与价格 - 哇谷IM-提供即时通讯IM开发-APP搭建私有化-公有云-私有化云-海外云搭建
新闻动态 - 哇谷IM-即时通讯热门动态博客聊天JM沟通APP
关于哇谷-哇谷IM-提供企业即时通讯IM开发-语音通话-APP搭建私有化-公有云-私有化云-海外云搭建
联系我们 - 哇谷IM-即时通讯IM私有化搭建提供接口与SDK及哇谷云服务
公有云和私有云之间有什么区别?类似融云、环信云、网易云、哇谷云?