目前处于消息队列还处于学习阶段,假如有什么不对的地方希望大佬们指出,谢谢!
1:吞吐量 -- 吞吐量数据来源 https://www.cnblogs.com/felixzh/p/6198070.html
单机124字节的写入测试
Kafka的吞吐量高达17.3w/s
这主要取决于它的队列模式保证了写磁盘的过程是线性IO。此时broker磁盘IO已达瓶颈。
RocketMQ吞吐量平均在11.6w/s
磁盘IO %util已接近100%。
RocketMQ的消息写入内存后即返回ack,由单独的线程专门做刷盘的操作,所有的消息均是顺序写文件。
RabbitMQ的吞吐量平均在5.93w/s
CPU资源消耗较高。它支持AMQP协议,实现非常重量级,为了保证消息的可靠性在吞吐量上做了取舍。我们还做了RabbitMQ在消息持久化场景下的性能测试,吞吐量在2.6w/s左右。
2:高可用性
kafka 分布式、主从
在具备选举功能 在Kafka里面,Master/Slave的选举,有2步:第1步,先通过ZK在所有机器中,选举出一个KafkaController;第2步,再由这个Controller,决定每个partition的Master是谁,Slave是谁。因为有了选举功能,所以kafka某个partition的master挂了,该partition对应的某个slave会升级为主对外提供服务。
主从自动切换 N个副本,允许N-1个失效;master失效以后自动从isr中选择一个主;
rocketMQ 分布式、主从
不具备选举 Master/Slave的角色也是固定的。当一个Master挂了之后,你可以写到其他Master上,但不能让一个Slave切换成Master。
rocketMq 的所有broker节点的角色都是一样,上面分配的topic和对应的queue的数量也是一样的,Mq只能保证当一个broker挂了,把原本写到这个broker的请求迁移到其他broker上面,而并不是这个broker对应的slave升级为主。
不支持自动切换 master失效以后不能向master发送信息,consumer大概30s(默认)可以感知此事件,此后从slave消费;如果master无法恢复,异步复制时可能出现部分信息丢失
RabbitMQ
主从,采用镜像模式实现,数据量大时可能产生性能瓶颈
主从自动切换 最早加入集群的slave会成为master;因为新加入的slave不同步master之前的数据,所以可能会出现部分数据丢失
3:集群负载实现
kafka采用zookeeper对集群中的broker、consumer进行管理,可以注册topic到zookeeper上;通过zookeeper的协调机制,producer保存对应topic的broker信息,可以随机或者轮询发送到broker上;并且producer可以基于语义指定分片,消息发送到broker的某分片上。
RabbitMq的负载均衡需要单独的loadbalancer进行支持。
RocketMQ采用nameserver服务对集群中的broker、consumer进行管理,具体实现和kafka类似,因为RocketMq是ali借鉴kafka,根据自身的业务场景所定制的消息对象,部分实现大同小异
4:扩容性
kafka通过zookeeper显示broker服务的自动注册与负载
RocketMQ通过nameserver实现同上的功能
RabbitMq通过loadbalancer实现,增加需要配置,涉及到内部数据冗余。
5:异常宕机后的消息回复处理
kafka:broker宕机会引起消息顺序乱序,再次消费会出现重复消费的情况;引起数据丢失
RabbitMQ:服务宕机,丢失数据严重,还会引起消息消费的重复,本身并不支持消息顺序性。
RocketMq: broker宕机不会引起消息顺序乱序,会引起数据少量丢失,不会引起重复消费
6:支持的协议
RabbitMQ 支持 AMQP(二进制),STOMP(文本),MQTT(二进制),HTTP(里面包装其他协议)等协议。
Kafka 使用自己的协议。
RocketMQ 使用JMS标准的自行一套协议
7:依赖性
Kafka 自身服务和消费者都需要依赖 Zookeeper。
RocketMQ 自身服务和消费者都需要依赖nameServer 类似于Zookeeper
RabbitMQ 需要依赖Erlang环境部署
8:并行度
kafka在消息存储过程中会根据topic和partition的数量创建物理文件,也就是说我们创建一个topic并指定了3个partition,那么就会有3个物理文件目录,也就说说partition的数量和对应的物理文件是一一对应的。
消费并行度依赖Topic配置的分区数,如分区数为10,那么最多10台机器来并行消费(每台机器只能开启一个线程),或者一台机器消费(10个线程并行消费)。即消费并行度和分区数一致。
RocketMQ
顺序消费方式并行度同Kafka完全一致
乱序方式并行度取决于Consumer的线程数,如Topic配置10个队列,10台机器消费,每台机器100个线程,那么并行度为1000。
RabbitMQ:
可一次抓取多条一起消费。
镜像模式下其实也是从master消费。
9:数据可靠性
RocketMQ支持异步实时刷盘,同步刷盘,同步Replication,异步Replication。可靠性很高。
Kafka 支持同步/异步复制,同步/异步刷盘。可靠性很高。
RabbitMQ producer支持同步/异步ack。支持队列数据持久化,镜像模式中支持主从同步。可靠性高。
总结:RocketMQ的同步刷盘在单机可靠性上比Kafka更高,不会因为操作系统Crash,导致数据丢失。
Kafka同步Replication理论上性能低于RocketMQ的同步Replication,原因是Kafka的数据以分区为单位组织,意味着一个Kafka实例上会有几百个数据分区,RocketMQ一个实例上只有一个数据分区,RocketMQ可以充分利用IO Group Commit机制,批量传输数据,配置同步Replication与异步Replication相比,性能损耗约20%~30%,Kafka没有亲自测试过,但是个人认为理论上会低于RocketMQ。
10:单机支持的队列数
Kafka单机超过64个队列/分区,Load会发生明显的飙高现象,队列越多,load越高,发送消息响应时间变长。Kafka分区数无法过多的问题。
RocketMQ单机支持最高5万个队列,Load不会发生明显变化
队列多有什么好处?
单机可以创建更多Topic,因为每个Topic都是由一批队列组成
Consumer的集群规模和队列数成正比,队列越多,Consumer集群可以越大
RabbitMQ 依赖于内存,队列存在于内存中,取决于内存大小
12:消费失败重试
Kafka 消费失败不支持重试。0.8.2版本后支持将失败的offset存储在zk中,可以通过修改offset来重新消费
RocketMQ 支持失败重试, offset存储在broker中,通过修改offset来进行重新消费
RabbitMQ 支持失败重试,会把消费失败的消息,丢到下一个消费者消费。
总结:例如充值类应用,当前时刻调用运营商网关,充值失败,可能是对方压力过多,稍后再调用就会成功,如支付宝到银行扣款也是类似需求。
13:严格的消息顺序
Kafka支持消息顺序,但是一台Broker宕机后,就会产生消息乱序,只限于单分区级别的顺序
RocketMQ支持严格的消息顺序,在顺序消息场景下,一台Broker宕机后,发送消息会失败,但是不会乱序,类似mysql Binlog分发拥有严格的消息顺序
RabbitMq 本身并没有严格的消息顺序性
14:消息回溯
Kafka 可以按照Offset回溯消息
RocketMQ支持按照时间来回溯消息
RabbitMQ 是典型的内存式堆积,但这并非绝对,在某些条件触发后会有换页动作来将内存中的消息换页到磁盘(换页动作会影响吞吐),或者直接使用惰性队列来将消息直接持久化至磁盘中。
本身并不支持消息回溯功能,Consumer ack以后,消息将被标记为删除,可用内存少于40%(默认),触发gc,gc时找到相邻的两个文件,合并right文件到left。
总结:典型业务场景如consumer做订单分析,但是由于程序逻辑或者依赖的系统发生故障等原因,导致今天消费的消息全部无效,需要重新从昨天零点开始消费,那么以时间为起点的消息重放功能对于业务非常有帮助。
15:Broker端消息过滤
Kafka RabbitMQ 不支持Broker端的消息过滤
RocketMQ支持两种Broker端消息过滤方式
根据Message Tag来过滤,相当于子topic概念
向服务器上传一段Java代码,可以对消息做任意形式的过滤,甚至可以做Message Body的过滤拆分。
16:实现语言
kafka -- Scala
RabbitMQ -- Erlang
RocketMQ -- java
17:消息确认机制
确认机制包括两部分,发送确认和消费确认。
RabbitMQ:
AMQP中,对于发送确认,使用事务机制,但开启事务的性能极低,大约会降低250倍(资料);
rabbitMQ为了提升性能,引入了流式的ack机制,相对于事务机制,有较大性能提升,但持久化的消息也至少需要消息写到磁盘,然后发送ack,相对于非持久化消息,也会有10倍左右的性能下降。
kafka:
通过写入offset来进行消息确认
kafka 0.9 以前的版本是将offset 存储在zookeeper上的,kafka在传输数据时,数据消费成功就会修改偏移量,这样就可以保证数据不会丢失而导致传输出错;
但是这也存在一个问题:那就是每次消费数据时都要将数据的offset写入一次,效率比较低,而且zookeeper与kafka的offset变化确认也需要走网络IO,这样就会给offset的维护带来不稳定性和低效。
kafka 0.9 以后,offset的使用了内部的roker来管理,这样仅仅只需要broker,而不要zookeeper来维护,都是将topic提交给__consumer_offsets函数来执行。 (使用broker来维护offset)
RocetMq:
回调函数返回ConsumeConcurrentlyStatus.CONSUME_SUCCESS,RocketMQ才会认为这批消息(默认是1条)是消费完成的。
如果这时候消息消费失败,例如数据库异常,余额不足扣款失败等一切业务认为消息需要重试的场景,只要返回ConsumeConcurrentlyStatus.RECONSUME_LATER,RocketMQ就会认为这批消息消费失败了。
为了保证消息是肯定被至少消费成功一次,RocketMQ会把这批消息重发回Broker(topic不是原topic而是这个消费租的RETRY topic),在延迟的某个时间点(默认是10秒,业务可设置)后,再次投递到这个ConsumerGroup。
而如果一直这样重复消费都持续失败到一定次数(默认16次),就会投递到DLQ死信队列。应用可以监控死信队列来做人工干预。
18:性能的稳定性
kafka 队列/分区多时性能不稳定,明显下降。
RocketMQ 消息堆积时性能稳定 队列较多、消息堆积时性能稳定
RabbitMQ 消息堆积时,性能不稳定、明显下降
19:管理后台
kafka: 官网不提供,第三方开源管理工具可供使用
rocketMq: 官方提供,rocketmq-console
rabbitmq: 官方提供
20: 安全性
kafka 目前支持 SSL、SASL 等认证机制。权限控制是指对客户端的读写操作进行权限控制,包括对消息或 Kafka 集群操作权限控制。权限控制是可插拔的,并支持与外部的授权服务进行集成。
RabbitMQ 而言,其同样提供身份认证(TLS/SSL、SASL)和权限控制(读写操作)的安全机制。
RocketMq 目前本身不支持安全认证机制。
总结
kafka
优点
1、在高吞吐、低延迟、高可用、集群热扩展、集群容错上有非常好的表现;
2、producer端提供缓存、压缩功能,可节省性能,提高效率。
3、提供顺序消费能力
4、提供多种客户端语言
5、生态完善,在大数据处理方面有大量配套的设施。
缺点
1、消费集群数目受到分区数目的限制。
2、单机topic多时,性能会明显降低。
3、不支持事务
RocketMQ
优点
1、在高吞吐、低延迟、高可用上有非常好的表现;消息堆积时,性能也很好。
2、api、系统设计都更加适在业务处理的场景。
3、支持多种消费方式。
4、支持broker消息过滤。
5、支持事务。
6、提供消息顺序消费能力;consumer可以水平扩展,消费能力很强。
7、集群规模在50台左右,单日处理消息上百亿;经历过大数据量的考验,比较稳定可靠。
缺点
1、相比于kafka,使用者较少,生态不够完善。消息堆积、吞吐率上也有所不如。
2、不支持主从自动切换,master失效后,消费者需要一定的时间才能感知。
3、客户端只支持Java
RabbitMQ
优点
1、在高吞吐量、高可用上较前两者有所不如。
2、支持多种客户端语言;支持amqp协议。
3、由于erlang语言的特性,性能也比较好; 使用RAM模式时,性能很好。
4、管理界面较丰富,在互联网公司也有较大规模的应用; 数据来自网络
缺点
1、erlang 语言难度较大。集群不支持动态扩展。
2、不支持事务、消息吞吐能力有限
3、消息堆积时,性能会明显降低
------------各个队列应用场景
Kafka应用场景
Kafka设计的初衷就是处理日志的,可以看做是一个日志系统,针对性很强,所以它并没有具备一个成熟MQ应该具备的特性
应当有一个非常好的运维监控系统,不单单要监控Kafka本身,还要监控Zookeeper。
对消息顺序不依赖,且不是那么实时的系统。
对消息丢失并不那么敏感的系统。
你有大量的事件(10万以上/秒)、你需要以分区的,顺序的,至少传递成功一次到混杂了在线和打包消费的消费者、你希望能重读消息、你能接受目前是有限的节点级别高可用
RabbitMQ应用场景
RabbitMQ的消息应当尽可能的小,并且只用来处理实时且要高可靠性的消息。
消费者和生产者的能力尽量对等,否则消息堆积会严重影响RabbitMQ的性能。
集群部署,使用热备,保证消息的可靠性。
AMQP协议本身比较复杂,参数比较多。
你有较少的事件(2万以上/秒)并且需要通过复杂的路由逻辑去找到消费者、你希望消息传递是可靠的、你并不关心消息传递的顺序、你需要现在就支持集群-节点级别
Erlang写的,很多人不熟悉,并且Mnesia出现问题好多人解决不了。
RocketMq应用场景
对于一些实时性较高,稳定性较好的业务。
对于消息消费的顺序性有严格的要求。
对消息丢失敏感的系统。
RocketMQ参考kafka实现,其并发与消息堆积有一定的优势,高并发处理和单机处理能力都比较出色,对于小公司是比较不错的选择。
中等的事件(5万以上/秒)、并且团队开发只涉及到java开发的、对消息传递可靠、横向拓展方便、需要严格的消息顺序性等有要求。
-------------选用RcoketMq需要解决的问题
不支持主从自动切换,master失效后,消费者需要一定的时间才能感知。对于单master时需要自己实现主备切换策略。
有比较完备的nameserver和消息队列服务本身的监控和报警策略。
RocketMq本身只支持java开发,协议是自定义的JMS标准实现,通用性不强。可以同公司多语言不能公用队列。
由于开源版并不支持分布式事务,可能需要自己搭建分布式事务的解决方案。
-------------选用RabbitMq需要解决的问题
Pub/Sub广播能力较弱
并不支持消息回溯。
对于消息堆积和高吞吐方面表现不是很好,消息堆积会使性能变得很差,设计时对于消息的大小和消息周期需要严格的要求。
erlang 语言难度较大,门槛高,底层优化与定制化难度大。
集群不支持动态扩展,添加消费者需要修改配置,需要自己实现动态配置。
-------------选用kafka需要解决的问题
需要自己处理消息的重复消费和消息重试机制。
一些高级队列都不支持,需要自己实现延迟队列、优先队列等
注意单机的多topic和多机分区数配置,配置不当会导致系统的性能不稳定。
本身对全局消息的顺序性并没有严格要求,只支持分区消息的顺序性。
服务宕机时,消息顺序性需要经行严格的控制,避免由于宕机引起的重复性消费。
技术选型:我们公司的业务更注重消息消费的可靠性,稳定性,以及有一定的消息堆积能力,良好的横向拓展和热部署,良好的后期维护优化性(公司基本都是java开发)
我们公司选择使用RocketMQ,使用多master(2台),多slave(2台)集群方式,异步刷盘形式进行数据同步,正处于开发测试期。
数据大部分参考来源地址:https://www.cnblogs.com/nov5026/p/9518520.html