Rocketmq vs Kafka

消息队列概念举例
小红是小明的姐姐,小红为了督促小明多读书,经常寻找好书给小明看,先前的方式是这样的,小红先问小明什么时候有空,然后把书送到小明跟前并且监督小明读完书再离开,久而久之,两人都有些厌烦,可书还是要读的,否则怎么跳槽加薪啊?

所以改变了方式,小红把小明需要看的书都放到书架上,小明直接从书架上拿下来书看即可,这时书架就是一个消息队列,小红是生产者,小明是消费者,这样做带来了四大好处

  • 小红不必费劲把书亲手交给小明,甚至不关心小明在不在,而是直接把书放到书架上,这样小明回到家看书架有书自然就去阅读,这样小红小明的时间都更自由了
  • 小明本身是能够自觉读书的,即使没有小红监督也能很好的完成读书任务,所以不需要小红一直监督着,能节省小红很大力气(涉及到异步发送)
  • 如果哪天强行加入了一位爱读书的小伙伴,他也直接去书架拿书(姑且理解为一本书被俩人拷贝后拿走)
  • 书都在书架上,小明读的快就早点看完,读的慢就晚会看完,都是可以的,不会和之前一样在小红的督促下拼命赶工完成读书任务,解放了小明

消息队列解决的问题

  • 解耦:消息队列要解决的最本质问题,你独立的扩展或修改两边的处理过程,只要确保它们遵守同样的接口约束即可,而不需要直接调用他人的接口,大大降低耦合度;如下图,消息队列诞生前B需要A找那个的数据只能掉A中的接口,后续更多的服务器B1,B2掉用了A接口,那就产生接口耦合了
    在这里插入图片描述
    案例中的三人(今后读书小组可能还会发展到n人的规模)不必受其它成员时间和习惯等因素的影响,只通过一个简单的书架来进行联系,他们眼里只有书架没有其它人,甚至后期小红都不关心谁来取书看,读书者们也不关心谁把书放到书架上的,和一个简单的消息队列打交道显然比和一个个人打交道简单的多

  • 广播(发布订阅模式):消息队列的基本功能之一。有了消息队列,我们只需要关心消息是否送达了队列,至于谁希望订阅,是下游的事情,无疑极大地减少了开发和联调的工作量。这里小红只需一个简答的放书动作就能使读书小队人人都能读书

  • 错峰与流控:讲用户请求存储在kafka,消费端也就是服务器端定额拉去处理请求,如果因为短暂的流量激增(比如秒杀业务和双11等场景)而扩展服务器那无疑是一种巨大的浪费,这样用于流量削峰场景,起到一个缓冲的作用。小红猛然发现一堆好书,此时如果还是采用之前的方法督促小红去完成小明会裂开,因为小明的读书能力和精力都是有限的,妈妈(用户)也很因为小明完不成任务恼怒,但有了书架后,小红就随缘了,把这一堆书放到书架上即可,并且会给妈妈打一个招呼,让小明慢慢看去吧,虽然速度还是那样,但总比小明累死强啊。
    在这里插入图片描述

  • 恢复性:系统的一部分组件失效时,不会影响到整个系统。消息队列降低了进程间的耦合度,所以即使一个处理消息的进程挂掉,加入队列中的消息仍然可以在系统恢复后被处理。

  • 最终一致性:两个系统的状态保持一致,要么都成功,要么都失败。最终一致性不是消息队列的必备特性,但可以依靠消息队列来做最终一致性。小红在书架上按个监视器,因为最终目的是要让小明把书读完的,而不是简单的把书放到书架上,小红通过监视器能知道小明的读书情况,大部分情况下小明肯定是能正常完成任务的,但也不排除一些意外如书丢了或者书错了导致小明没有成功读完书,小红也能知道小明没有完成任务

  • 异步通信:很多时候,用户不想也不需要立即处理消息。消息队列提供了异步处理机制,允许生产者把一个消息放入队列,但消费者并不立即处理它。生产者想向队列中放入多少消息就放多少,然后消费者在需要的时候再去处理它们。小明突然身体不舒服不想读书,难道小红还要等小明身体回复再监视他读完吗?并不是这样,我们只需要让小明立一个FLAG,然后小红把这个flag汇报给妈妈(公司用户),让妈妈知道至少小明是有这个意愿读书的,等小明身体恢复就会立刻爬起来读书。
    在这里插入图片描述
    总结

kafka优点

  • 解耦合,耦合的状态表示当你实现某个功能的时候,是直接接入当前接口,而利用消息队列,可以将相应的消息发送到消息队列,这样的话,允许你独立的扩展或修改两边的处理过程,只要确保它们遵守同样的接口约束。即便接口出了问题,将不会影响到当前的功能。
  • 可恢复性:系统的一部分组件失效时,不会影响到整个系统。消息队列降低了进程间的耦合度,所以即使一个处理消息的进程挂掉,加入队列中的消息仍然可以在系统恢复后被处理。
  • 缓冲:有助于控制和优化数据流经过系统的速度,解决生产消息和消费消息的处理速度不一致
    的情况。
  • 异步处理,异步处理替代了之前的同步处理,异步处理不需要让流程走完就返回结果,可以将消息发送到消息队列中,然后返回结果,剩下让其他业务处理接口从消息队列中拉取消费处理即可。
  • 流量削峰,高流量的时候,使用消息队列作为中间件可以将流量的高峰保存在消息队列中,从而防止了系统的高请求,减轻服务器的请求处理压力。

kafka缺点
1 引入复杂度,书架本身就是多出来的
2 暂时不一致,其实最终一致性和展示不一致性是同一概念,先前的方式小红监督小明读书,虽然费劲,但如果妈妈问小红小明的读书情况那么小红可以理直气壮的说小明读完了or没读完,但现在小红只能模糊的回答:应该读完了或者快读完了,也就是说中间存在一段时间就是我们认为小明已经读完了,但其实小明正在阅读还没读完,但最终小明会读完的,这就是最终一致性
3 无法获取反馈,采用这种方式可以看出来小红

消息队列的特征

  • 先进先出:队列的基本特征
  • 容错性:允许集群中节点失败
  • 可扩展性:mq集群支持热扩展
  • 持久化:MQ的不只是一个部分场景的辅助工具,也能像数据库一样存储核心的数据。
  • 分布式:在现在大流量、大数据的使用场景下,只支持单体应用的服务器软件基本是无法使用的,支持分布式的部署,才能被广泛使用。而且,MQ的定位就是一个高性能的中间件。

kafka vs rocketmq

1 应用场景

  • RocketMQ以电商为背景广泛应用在订单,交易,充值,流计算,消息推送binglog分发等场景,主要是用于削峰填谷,支持双十一海量消息考验
  • kafka定位日志的收集与传输,用户活动跟踪,运营指标

2数据可靠性

  • RocketMQ支持异步实时刷盘,同步刷盘,同步Replication,异步Replication
  • Kafka使用异步刷盘方式,异步Replication,同步Replication

由于RocketMQ支持同步刷盘和同步Replication,所以可靠性较高。但对于kafka就算异步刷盘,当broker挂掉时,数据是不会丢失的,只有系统crash才会造成丢失,但是在集群模式下,可以设置同步replication,如果是同步replication,复制因子为N,允许N-1个服务所
在的系统crash,而不会丢失数据

3 性能对比

  • Kafka的TPS跑到单机百万,主要是由于Producer端将多个小消息合并,批量发向Broker。
  • RocketMQ只有7万
    • Producer通常使用Java语言,缓存过多消息,GC是个很严重的问题
    • Producer调用发送消息接口,消息未发送到Broker,向业务返回成功,此时Producer宕机,会导致消息丢失,业务出错
    • Producer通常为分布式系统,且每台机器都是多线程发送,我们认为线上的系统单个Producer每秒产生的数据量有限,不可能上万。
    • 缓存的功能完全可以由上层业务完成。

4单机支持的队列数

  • Kafka单机超过64个队列/分区,Load会发生明显的飙高现象,队列越多,load越高,发送消息响应时间变长。
  • RocketMQ单机支持最高5万个队列,Load不会发生明显变化

队列多有什么好处?
单机可以创建更多Topic,因为每个Topic都是由一批队列组成,Consumer的集群规模和队列数成正比,队列越多,Consumer集群可以越大

5 消息投递实时性
Kafka的consumer端不支持push被动接收消息,只支持pull主动拉去消息,如果使用短轮询方式,实时性取决于轮询间隔时间,实时性较弱,后续版本推出了长轮询增强了实时性,长轮询会造成资源浪费,所以新版本kafka会有一个timeout参数,如果timeout时间内都没有producor向kafka发送的新消息,那么bkafka就会暂停一段时间再次进行拉取,减少资源消耗
RocketMQ的conusmer端同时支持push和pull两种消息获取形式,使用长轮询,同Push方式实时性一致,消息的投递延时通常在几个毫秒。

6 消费失败重试
Kafka先前消费失败不支持重试,后期支持

 message.send.max.retries=100

 retry.backoff.ms=5000

 不过这个重试时间是固定的,通常希望有个倍数。消息不丢失主要依赖ack机制,但是可能会造成重复,这个消息中间件通常希望通过业务来解决,最简单的办法,表中设置一个唯一键,或者写业务数据的同时,增加一张日志表,保证唯一。

ack机制:

  • 0:这意味着producer无需等待来自broker的确认而继续发送下一批消息。这种情况下数据传输效率最高,但是数据可靠性确是最低的。
  • 1:(默认)这意味着producer在ISR中的leader已成功收到的数据并得到确认后发送下一条message。
    如果leader宕机了,则会丢失数据。
  • -1(或者是all):producer需要等待ISR中的所有follower都确认接收到数据后才算一次发送完成,可靠性最高。但是这样也不能保证数据不丢失,比如当ISR中只有leader时。

RocketMQ消费失败支持定时重试,每次重试间隔时间顺延

总结:例如充值类应用,当前时刻调用运营商网关,充值失败,可能是对方压力过多,稍后在调用就会成功,如支付宝到银行扣款也是类似需求。
这里的重试需要可靠的重试,即失败重试的消息不因为Consumer宕机导致丢失。

消息顺序
Kafka支持消息顺序,但是一台Broker宕机后,就会产生消息乱序
RocketMQ支持严格的消息顺序,在顺序消息场景下,一台Broker宕机后,发送消息会失败,但是不会乱序

定时消息
Kafka不支持定时消息
RocketMQ支持两类定时消息
开源版本RocketMQ仅支持定时Level
阿里云ONS支持定时Level,以及指定的毫秒级别的延时时间

分布式事务消息
Kafka不支持分布式事务消息
阿里云ONS支持分布式定时消息,未来开源版本的RocketMQ也有计划支持分布式事务消息

虽然kafka不支持分布式事务,但是大多互联网应用采用分布式事务的很少,主要是因为

  • 缺乏大规模应用的成功案例
  • 死锁风险,特别是在大并发量下,现在大多是以客户端作为协调者,而客户端通常部署在虚拟机或者docker这种容器中,一旦挂掉,数据库只能等客户端恢复解锁。
  • 一般使用rocketmq或者kafka的对并发量要求都比较高,使用分布式事务是一个需要考虑的问题。

Kafka有两个等级的api,大多使用highLevel的,还有一个simple Api,可以自己控制offset的存储,这样就可以变向实现分布式事务了。

消息查询
Kafka不支持消息查询
RocketMQ支持根据Message Id查询消息,也支持根据消息内容查询消息(发送消息时指定一个Message Key,任意字符串,例如指定为订单Id)

消息查询对于定位消息丢失问题非常有帮助,例如某个订单处理失败,是消息没收到还是收到处理出错了。
但是没人在意日志中那一条数据有问题,比较实用

消息回溯
Kafka理论上可以按照Offset来回溯消息
RocketMQ支持按照时间来回溯消息,精度毫秒,例如从一天之前的某时某分某秒开始重新消费消息

典型业务场景如consumer做订单分析,但是由于程序逻辑或者依赖的系统发生故障等原因,导致今天消费的消息全部无效,
需要重新从昨天零点开始消费,那么以时间为起点的消息重放功能对于业务非常有帮助。

消费并行度
在这里插入图片描述

kafka:Consumergroup:各个consumer(consumer 线程)可以组成一个组(Consumer group ),partition中的每个message只能被 组(Consumer group ) 中的一个consumer( consumer 线程 )消费,如果一个message可以被多个 consumer( consumer 线程 ) 消费的话,那么这些consumer必须在不同的组。Kafka不支持一个partition中的message由两个或两个以上的同一个consumer group下的consumer thread来处理,除非再启动一个新的consumer group。所以如果想同时对一个topic做消费的话,启动多个consumer group就可以了,所以Kafka的消费并行度依赖Topic配置的分区数,一个分区只能被消费者中的一个消费者线程消费,比如分区数为10,那么一个消费者组最多10个消费者,大于10的部分就浪费掉了,但无论消费者组消费者数目多么少,哪怕只有一台机器,这一台机器也能消费掉全部的partition,也就是所有的分区都会一个不漏的被消费掉,最优的设计就是consumer group下的consumer thread的数量等于partition数量,这样效率是最高的。扩展策略:如果觉得效率不高的时候,可以加partition的数量来横向扩展,再加新的consumer thread去消费,如果想多个不同的业务都需要这个topic的数据,起多个consumer group就好了

那么最多10台机器来并行消费(每台机器只能开启一个线程),或者一台机器消费(10个线程并行消费)。即消费并行度和分区数一致。

RocketMQ消费并行度分两种情况

顺序消费方式并行度同Kafka完全一致
乱序方式并行度取决于Consumer的线程数,如Topic配置10个队列,10台机器消费,每台机器100个线程,那么并行度为1000。

消息轨迹
Kafka不支持消息轨迹
阿里云ONS支持消息轨迹

Broker端消息过滤
Kafka不支持Broker端的消息过滤
RocketMQ支持两种Broker端消息过滤方式
根据Message Tag来过滤,相当于子topic概念
向服务器上传一段Java代码,可以对消息做任意形式的过滤,甚至可以做Message Body的过滤拆分。

消息堆积能力
理论上Kafka要比RocketMQ的堆积能力更强,不过RocketMQ单机也可以支持亿级的消息堆积能力,我们认为这个堆积能力已经完全可以满足业务需求。

架构对比

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值