Kafka与Rocketmq的区别

系统一直使用的Kafka用来消费业务流水,最近在群里听到反馈说希望转到Rocketmq,支持更多的业务功能,因此去了解了一下,发现相比之下Kafka确实应用场景

太少了,基本就是消费日志,相比之下Rockmq有很多优秀的特性,下面具体介绍一下。

Kafka

首先介绍一下Kafka,Kafka是一个分布式、分区的、多副本的、多订阅者,基于zookeeper协调的分布式日志系统,比较常用于日志收集系统,和消息系统等

topic类似数据库的表名,代表一个类别,一个topic中的数据分为多个partition,每个partition中的数据由多个segment文件存储,每个partition中的数据是有序的,因此如果

想保证有序,需要将topic的partition数目设置为1

1、可以以时间复杂度为O(1)的方式提供消息持久化能力,对TB以上的数据也能保持常数时间的访问性能

2、高吞吐率

3、支持Kafka server间的消息分区,保证每个partition内的消息顺序传输

4、支持离线数据处理和实时数据处理

5、支持在线水平扩展

Kafka的高可用(HA High Availability)

通过多副本机制实现,每个partition的数据都会同步到其他机器上,形成自己的多个replica副本,然后所有副本选举出一个leader,

生产和消费都只和leader交互,其他副本都是follower,写的时候,producer写leader,leader将数据写入本地磁盘,然后其他follower来pull数据,全部同步好以后发送ack给leader,返回返回成功,所有follower即为ISR,即可用且消息量与leader相差不多的副本集合

这种情况下如果某个broker宕机了,如果他是leader,那么其他副本会重新选举出一个leader,继续使用新的leader,保证了高可用性

Kafka的高性能

1、批处理,从生产者发送到消费者消费,Kafka都进行了批处理操作,即生产者发送一条消息无论同步还是异步,Kafka都不会立即把消息发送出去,而是先放到内存中,将多个消息组成一个批消息,发送到broker端,在broker端也不会拆开,而是做为批消息写入磁盘,同步到其他副本,消费者也是这个批消息,然后在客户端将批消息还原为一条条消息

buffer.memory:33554432 (32m) 调整未发送出去消息的缓冲区大小 

batch.size:16384一个批次的数据字节大小,太大占用缓冲区多,但是不会延迟(有其他触发机制)而 太小会频繁提交消息效率低下

2、消息压缩  compression.type:none 默认发送不压缩,可以配置合适的压缩方式(snappy/gzip/lz4可选,推荐 少CPU,高性价比的snappy)

3、顺序读写提升磁盘性能,如果磁盘随机读写,需要进行寻址,而Kafka使用顺序读写

4、pagecache加速读写,pagecache是操作系统给磁盘文件在内存中建立的缓存,当进程准备读取文件内容时,操作系统首先看待读取的数据所在的页是否在页缓存中,如果不在,就需要读取磁盘,然后将数据同步到页缓存,Kafka同样提供了同步刷盘,即避免因为宕机导致页缓存数据还未完成同步导致的数据丢失,但是实际没必要考虑这个因素,因为消息可靠性可以由多副本来解决,同步刷盘会带来性能的影响  

Page Cache是系统级别的缓存(内核缓冲区),当上层有写操作时,操作系统只是将数据写入pagecache,同时标记page属性为dirty,当读操作发生时,先从pagecache中查找,如果发生缺页才进行磁盘调度,pagecache避免了在JVM内部缓存数据,避免了不必要的GC,以及内存空间占用,如果Kafka重启,它会失效,而操作系统管理的PageCache依然可以继续使用。

producer把消息发到broker后,数据并不是直接落入磁盘的,而是先进入PageCache。PageCache中的数据会被内核中的处理线程采用同步或异步的方式写回到磁盘。Consumer消费消息时,会先从PageCache获取消息,获取不到才回去磁盘读取,并且会预读出一些相邻的块放入PageCache,以方便下一次读取如果Kafka producer的生产速率与consumer的消费速率相差不大,那么几乎只靠对broker PageCache的读写就能完成整个生产和消费过程,磁盘访问非常少。

5、零拷贝,Kafka通过将pagecache中的数据直接复制到socket的缓冲区,减少了内核态到用户态再到socket缓冲区的复制过程

传统的网络I/O过程:

1.操作系统从磁盘把数据读到内核区2.用户进程把数据从内核区copy到用户区

3.然后用户进程再把数据写入到socket,数据流入内核区的Socket Buffer上

4.最后把数据从socket Buffer中发送到到网卡,这样完成一次发送

可以发现,同一份数据在内核Buffer与用户Buffer之间拷贝两次:

 

 

但是通过SendFile(又称zero copy)优化后,直接把数据从内核缓冲区copy到socket缓冲区,然后发送到网卡,避免了在内核Buffer与用户Buffer来回拷贝的弊端:

 

 

不仅是Kafka,Java的NIO提供的FileChannle,它的transferTo、transferFrom方法也利用了这种在内核区完成数据传输的功能。

Rocketmq

RocketMQ由NameServer注册中⼼集群、Producer⽣产者集群、Consumer消费者集群和若⼲Broker(RocketMQ进程)组成,它的架构原理是这样的:

1. Broker在启动的时候去向所有的NameServer注册,并保持⻓连接,每30s发送⼀次⼼跳

2. Producer在发送消息的时候从NameServer获取Broker服务器地址,根据负载均衡算法选择⼀台服务器来发送消息

3. Conusmer消费消息的时候同样从NameServer获取Broker地址,然后主动拉取消息来消费

rocketmq没有使用zookeeper的原因:

1. 根据CAP理论,同时最多只能满⾜两个点,⽽zookeeper满⾜的是CP,也就是说zookeeper并不能保证服务的可⽤性,zookeeper在进⾏选举的时候,整个选举的时间太⻓,期间整个集群都处于不可⽤的状态,⽽这对于⼀个注册中⼼来说肯定是不能接受的,作为服务发现来说就应该是为可⽤性⽽设计。

2. 基于性能的考虑,NameServer本身的实现⾮常轻量,⽽且可以通过增加机器的⽅式⽔平扩展,增加集群的抗压能⼒,⽽zookeeper的写是不可扩展的,⽽zookeeper要解决这个问题只能通过划分领域,划分多个zookeeper集群来解决,⾸先操作起来太复杂,其次这样还是⼜违反了CAP中的A的设计,导致服务之间是不连通的。

3. 持久化的机制来带的问题,ZooKeeper 的 ZAB 协议对每⼀个写请求,会在每个 ZooKeeper 节点上保持写⼀个事务⽇志,同时再加上定期的将内存数据镜像(Snapshot)到磁盘来保证数据的⼀致性和持久性,⽽对于⼀个简单的服务发现的场景来说,这其实没有太⼤的必要,这个实现⽅案太重了。⽽且本身存储的数据应该是⾼度定制化的。

4. 消息发送应该弱依赖注册中⼼,⽽RocketMQ的设计理念也正是基于此,⽣产者在第⼀次发送消息的时候从NameServer获取到Broker地址后缓存到本地,如果NameServer整个集群不可⽤,短时间内对于⽣产者和消费者并不会产⽣太⼤影响。

rocketmq的事务

实现原理如下:

1. ⽣产者先发送⼀条半事务消息到MQ

2. MQ收到消息后返回ack确认

3. ⽣产者开始执⾏本地事务

4. 如果事务执⾏成功发送commit到MQ,失败发送rollback

5. 如果MQ⻓时间未收到⽣产者的⼆次确认commit或者rollback,MQ对⽣产者发起消息回查

6. ⽣产者查询事务执⾏最终状态

7. 根据查询事务状态再次提交⼆次确认

最终,如果MQ收到⼆次确认commit,就可以把消息投递给消费者,反之如果是rollback,消息会保存下来并且在3天后被删除。

相比于Kafka,rocketmq具有的优势主要有:

1、支持事物型消息(消息发送和db操作保持两方的一致性)

A,B(均存在DB操作)两方需保证事物一致性,通过引入中间层MQ,A和MQ保持一致性(异常情况下通过MQ反查A接口实现check),B和MQ保持一致性(通过重试),

从而达到最终事务一致性(大事务=小事务+异步)

2、支持结合rocketmq的多个系统之间数据最终一致性(多方事物)

3、支持18个级别的延迟消息

4、支持指定次数和时间间隔的失败消息重发

5、支持consumer端tag过滤,减少不必要的网络传输

6、支持重复消费(这个Kafka也支持,理论上可以按照offset来回溯消息)

7、rocketmq的注册中心为name server,Kafka为zookeeper

与Kafka的优劣对比

1、单机吞吐量: Kafka比rocketmq要高,这事Kafka最大的优点,Kafka会根据topic和partition创建物理文件,partition的数量和对应的物理文件是一一对应的

rocketmq只有一个物理文件,即commitLog,queue的数量是在commitLog里体现的,真正存储消息的只有commitLog一个文件,由于Kafka的topic一般有多个patition,因此Kafka的数据写入速度比rocketmq高出一个量级,但是如果topic过多,导致写入的文件数量过多,会导致原先的顺序写转为随机写,性能急剧下降

Kafka是基于分区,每个分区一个文件,而rocketmq是基于队列,只有一个文件,即commitLog

Kafka的tps能达到单机百万,主要是因为producter端将多个小消息合并,批量发向broker

而rocketmq没这么做的原因是:

  1. Producer通常使用Java语言,缓存过多消息,GC是个很严重的问题
  2. Producer调用发送消息接口,消息未发送到Broker,向业务返回成功,此时Producer宕机,会导致消息丢失,业务出错
  3. Producer通常为分布式系统,且每台机器都是多线程发送,我们认为线上的系统单个Producer每秒产生的数据量有限,不可能上万。
  4. 缓存的功能完全可以由上层业务完成。

2、topic数量: rocketmq可以支持成百上千的topic,而Kafka在达到几百个topic的时候吞吐量就会大幅下降,因为Kafka的topic数量不能太多,受到zookeeper协调策略和消息文件存储设计的制约

3、rocketmq支持异步刷盘,同步刷盘,同步replication,异步replication,Kafka使用异步刷盘,异步replication,同步刷盘在单机可靠性上比Kafka更高,不会因为操作系统crash导致数据丢失,Kafka的replication以topic为单位,支持主机宕机,备机自动切换,但是由于是异步replication,切换后可能会有数据丢失,同时如果leader重启,会与已经存在的leader产生冲突,   rocketmq不支持master宕机,slave自动切换为master,即master宕机以后,slave只能提供读

发送消息:kafka默认使用异步发送的形式,有一个memory buffer暂存消息,同时会将多个消息整合成一个数据包发送(batch.size),这样能提高吞吐量,但对消息的实效有些影响;rocketmq可选择使用同步或者异步发送。

发送响应:kafka的发送ack支持三种设置:0 消息存进memory buffer就返回;1 等到leader收到消息返回,all 等到leader和isr的follower都收到消息返回,当然kafka都是异步刷盘。rocketmq都需要等broker的响应确认,有同步刷盘,异步刷盘,同步双写,异步双写等策略,相比于kafka多了一个同步刷盘。
 

4、rocketmq在队列上保持有序,同时也可以设置普通顺序还是严格顺序,Kafka只支持partition上有序

5、broker端消息过滤,Kafka不支持,RocketMQ支持两种Broker端消息过滤方式

  • 根据Message Tag来过滤,相当于子topic概念
  • 向服务器上传一段Java代码,可以对消息做任意形式的过滤,甚至可以做Message Body的过滤拆分。

推荐博客:

rocketmq和Kafka区别

https://blog.csdn.net/zuojunyuan/article/details/108883234

rocketmq介绍

http://www.dockone.io/article/9726

 

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值