从rocketmq到kafka

author author     2023-03-23     179

关键词:

参考技术A 在基于了解或掌握其他同类MQ的基础知识上,怎么比较快速的掌握kafka的核心设计,确保在使用的过程中做到心中有数,做到知其然并知其所以然?本篇文章主要是笔者在已有的rmq的基础上学习kafka的思路以及过程的总结。

ps、rmq指RocketMQ

ps、文章写着写着发现有点长,应该挺乱了……

ps、因为是学习笔记,所以就这样吧,随便看看……

带着问题去学习新的技能,也许会更贴近自己原有的知识储备,也能更好的把新知识纳入自己原有的知识体系并加以补充或者延展,形成更完整的知识脉络。基于原有的rmq的知识体系,在提前梳理了几个相关的,并且浅显的问题,主要是两个方面的内容,一类是MQ模型中生产者客户端的设计与消费者客户端的设计,一类是服务端的总体架构设计。

服务端的总体架构设计

客户端的总体架构设计

相信很多人不管是在面试中,还是在做MQ选型时,都会遇到几个问题,比如Kafka在超过2k的topic时性能会急剧下降,但是rmq在超过2k的topic时性能不存大规模下降,比如Kafka是一个分布式消息队列中间件,而rmq更像一个单机版消息队列中间件等。这些问题的背后,正是两个消息中间件在架构设计上的差异性所导致的,各有优劣势,我们更多的关注设计思路。先看这几个问题。

在rmq服务端写入时,完全是基于commit log 做log append,避免了磁盘的随机读写,再配合零拷贝等技术特性,成为了MQ的高并发利器。而由于RMQ的全量日志都维护在commit log,这也是其余kafka的一个架构设计上的区别。相信初步了解过kafka的同学,都应该知道其设计理念中关于分区与副本的概念,一个topic在集群中存在多个分区,一个分区在集群中存在多个副本,不同的topic之间分区是互不关联的,当单机维护超过2k的topic时,意味着单机存在2k多个分区,即便topic内日志采用log append,那么在高并发写入刷盘时,磁头在这些分区的副本文件上移来移去,性能自然会随之下降,看起来像是‘随机读写’。

这个说法是在一个中间件爱好群里看到大家在讨论时聊到的,感觉相当有意思,这种看法背后又是怎么的逻辑呢?首先,网上能找到的二者大量的对比都是基于单机的对比,集群对比很少。从分区+副本的思路来看,kafka的部署架构看起来是多个broker组成集群,但是内部运转逻辑是分区维度的多副本间高可用,即topic在多个broker之间做高可用的保证,而副本间的运转逻辑是基于zookeeper的ZAB机制。反观rmq最开始的架构确实主从架构,看起来更简单,但是可用性的保证上完全不一样,由于所有的topic都在主节点上,主节点挂了整个集群就运转不下去了,因为只有主可以支持写,所以rmq推荐使用双主架构,后来才引入raft协议支持选举,但依旧是基于broker的选举。二者最大的区别在于,集群中某个节点挂机对于整个集群的影响程度不同,毫无疑问,rmq显得更重。同样的多节点集群中,每个kafka broker都在提供读写能力,因为不同的topic的副本散落在各个broker中,而每个topic的leader副本也会分散在整个集群中,而rmq则不同,所以理论上kafka集群能提供的吞吐量应该会比rmq更高。

从前两个问题,提到了几个很核心的概念,包括分区,副本,而这也是kafka最核心设计内容。kafka的分区这个设计很有意思( 关于kafka分区 ),kafka的集群是一个整体,对于topic而言,分区个数相当于多少个可读写节点,一个分区下存在多个副本组成一个分布式可选主的‘集群’。

如上图,在一个kafka集群中,部署了三个服务端节点,在topic-a创建时,创建了2个分区,3个副本,在这个部署下,提供读写能力的只有broker1节点上1分区的副本,broker2节点上2分区的副本。对于部署节点broker而言并无主次之分,分区与分区间相互独立,分区内副本间组成集群为topic-a : partation-1提供服务。topic 与 分区 可以看做是逻辑概念,副本为物理概念。所以,前文提到弱化broker的概念就在于,它是基于分区提供服务,这个与rmq的设定完全不同,也许是先入为主的关系,又或者在rmq架构中broker的设定更像是mysql的主从设定,rmq的broker理解起来更简单。

那么什么是isr, asr? 在说这个之前,先说说对于一条消息而言,kafka理论上应该如何在兼顾一定性能的情况下获取更高的可靠性?请求写入分区1的leader副本,就能保证数据一定不丢失吗?如果此时leader节点宕机发生选举,由于follower节点还没同步leader数据,那是不是一段时间内的数据就丢失了呢?那为了更高的可靠性,是不是可以选择等所有副本都同步到当前消息才算本次写入成功?follower节点的数据时从leader节点复制而来(此处会抽象一个很常见的水位高低的概念,但是还没详细了解,暂时忽略),那如果follower节点的数据跟leader节点的数据很接近的话,那么复制会很快完成,但是如果某个follower节点的数据落后leader的节点很多,等待完全同步需要更长的时间,毫无疑问将会引发灾难性的结果。那么,有没有一种相对均衡,可接受的方案,比如只等待落后leader节点数据量较低的follower节点成功复制就算成功?技术方案的选择往往都是取舍,特别是多副本间的数据一致性的问题。

isr集合,俗称副本同步集。kafka并非是根据副本间数据复制的偏移量来计算集合,而是根据数据同步的时间间隔(参数为 **[replica.lag.time.max.ms](http://replica.lag.time.max.ms/)** ,默认为10s),将相同分区中leader与follower之间同步消息的时间间隔不超过设置的阔值的副本放入isr集合,而asr则表示所有副本集合。

有了isr集合,那么副本数据间的一定程度的一致性,可以转为只要写入isr成功就算成功,但是就算这样就可以了吗?如果leader副本宕机了集群要重新选举,选出了一个落后的follower副本,那数据还是照样丢了,kafka是不是要确保一个非isr集群的副本不能参加选举?其次,如果isr长期只有一个节点,那是不是风险依旧很高?鉴于这些问题,另外提供两个参数以供解决(参数 unclean.leader.election.enable , 设置为false表示非isr节点不参与选举, 参考文章 。参数 min.insync.replicas ,最小同步副本个数,既isr集合大小,推荐设置asr -1 ,具体视副本数大小设定 ), 推荐查阅的isr文章 。在兼顾kafka的性能与可靠性间取舍,通过生产者端的 acks 参数来设定。

在聊kafka的isr集合时,让笔者想到rmq的几个参数,客户端的同步/异步发送,服务端的同步刷盘,异步刷盘,同步复制,异步复制,由于后期rmq基于raft协议做集群的选举,并不知道是否还有其他的副本间数据一致性的方案,并且也有数年未翻过rmq的源码,细节了解不多,所以不好下定论,但是从颗粒度的设计上无疑rmq会更粗糙一些,理解上也更加简单,但是,个人认为kafka的设计相对更高级,在生产环境中使用会更加放心。

以上大致也谈了kafka集群的部署,以及isr合集,分区副本等概念,还未谈及kafka服务端的日志的设计,从网上大致了解了一番,感觉跟rmq的设计有相似之处(rmq的设计理念很多也是借鉴了kafka),这块内容待后续补充吧。

前文带着问题来学习时提到客户端中生产者我们需要关注的内容,包括同步异步,负载均衡,流控等的内容。生产者的本质是什么,无疑是如何将消息正确的投递到服务端。由于目前笔者使用的是Java,所以直接翻阅了Java语言实现的客户端程序(spring-kafka-2.1.7, kafka-client-1.0.1),其他语言实现的客户端程序可能存在一定差异。先提供几篇学习资料的传送门: 初识kafka producer 、 Kafka消息发送流程 、 Sender线程详解

不得不提的几个参数

其中笔者觉得有几个点是需要重点关注的,如下:

1、分区器是重点需要关注

分区器的逻辑相对简单,但是却要关注,因为它很重要,它在做选择分区的活。

2、acks=0的逻辑(其他的逻辑需要原来服务端的响应,可以看看NetworkClient#handleCompletedReceives)

3、RecordAccumulator#ready 中判断了什么

4、回调里究竟做了什么?

5、流控问题

应该算初步掌握Kafka Producer,至少日常使用应该是没问题了,前文提到同步、异步、流控、负载均衡等问题都应该有了了解,其他的细节有时间有遇到问题再单独补充吧~

消费端的核心流程一般有三个:1、元数据同步过来后的负载均衡,消费端剔除,reblance等。2、消息的poll流程。3、offset commit流程。先提供几篇学习资料: 线程拉取模型 , 核心参数 , 重平衡

基本上看完了消费者客户端的核心流程,总体感觉相对复杂。相比rmq而言,印象中,rmq的rebalance的设计更简单一些,有一条线程去做reblance,有一条线程去做poll,线程间相互隔离,relbance的流程不会阻塞poll流程。并且由于是客户端均分负载,每个客户端只负责从ns中拿到元数据,然后客户端按照算法本地均分,结果并不会反馈给服务端,既rmq的客户端如果采用算法不一样,就会有风险。

1、kafka的reblance中需要引入一个协调器Coordinator,客户端从本地缓存的元数据中随机找到一个可用的leader节点,向其发送寻找协调器的节点。主要向服务端带了一个grouopId的数据去找到合适的协调器,寻找协调器的过程中是超时阻塞的。

2、找到协调器后,判断是否需要加入总的分配分组(仅看选择了自动分配的订阅类型的)。判断上一次分配的元数据跟当前的元数据是否发生变更,判断已加入的主题列表与当前的主题列表是否发生变更,已经是否需要rejoin的标记位。

3、确认需要加入分组后,如果是自动分配分区的场景下,需要拉去最新的元数据,之后进入reblance阶段。

4、reblance分为两个阶段,一个是prepare阶段,主要做包括(自动的)同步本地的最新commit,触发reblance钩子函数,重置分组订阅关系,还需要停掉当前的心跳(防止它影响分配的过程)。另外一个就是加入阶段,向服务端发起请求后等待结果异步回调,回调中会判断如果当前的节点是leader节点,则执行分配逻辑,并将分配逻辑发给服务端。如果当前的节点是follower节点,则向服务端发送空的分配结果,并等待服务端回调最终的分配结果。等服务端返回最终结果都是阻塞状态。

5、执行协调器分配完成。

从中可以理解,分配的逻辑在客户端中的某一个节点,客户端分配完成后将结果返回给服务端,服务端再分发给各个节点,确保整个客户端集群的分配算法是统一的。触发reblance之后,如果集群中的节点发生变更,会怎么触发第二次reblance?在客户端父服务端的交互中,比如通过心跳上报时,服务端返回 Errors.REBALANCE_IN_PROGRESS ,客户端重置本地 needRejoin 标记位,等待下一次发起poll时进行第二次reblance。同理,提交偏移量时会返回需要reblance。

rocketmq和kafka到底选哪个

参考技术A1、适用场景kafka适合日志处理rocketmq适合业务处理结论:两者没有区别,根据具体业务定夺2、性能kafka单机写入TPS号称在百万条/秒rocketmq大约在10万条/秒结论:追求性能方面,kafka单机性能更高3、可靠性kafka使用异步刷... 查看详情

分布式消息队列rocketmq&kafka--消息的“顺序消费”

...。Consumer按1,2,3。。。顺序消费。但实际情况却是:无论RocketMQ,还是Kafka,缺省都不保证消息的严格有序消费!这个特性看起来很简单,但为什么缺省他们都不保证呢?“严格的顺序消费”有多么困难下面就从3个方面来分析一下... 查看详情

rocketmq与kafka对比(18项差异)

转自:https://github.com/alibaba/RocketMQ/wiki/rmq_vs_kafka淘宝内部的交易系统使用了淘宝自主研发的Notify消息中间件,使用MySQL作为消息存储媒介,可完全水平扩容,为了进一步降低成本,我们认为存储部分可以进一步优化,2011年初,Link... 查看详情

你应该知道的rocketmq(代码片段)

...是使用的是Kafka,而现在换了公司之后,更多的使用的是Rocketmq,本篇文章会尽力全面的介绍RocketMQ和Kafka各个关键点的比较,希望大家读完能有所收获。RocketMQ前身叫做MetaQ,在MeataQ发布3.0版本的时候改名为RocketMQ,其本质上的设计... 查看详情

rocketmq使用(代码片段)

rocketmq 基本使用可以看官网和官网给的demo.https://github.com/apache/rocketmq/tree/master/example这里主要说明几个点:rocketmq  发送类型常用:1,普通消息.(可以获取发送结果,失败了重试)2,有序消息.(秒杀,等需要有序的消费场景)3,事... 查看详情

rocketmq与kafka的区别

...性不满足。因此,阿里中间件团队基于Java重新编写了RocketMQ,定位于不仅限于日志场景的可靠消息传输。目前,RocketMQ在阿里集团被广泛应用于订单、充值、交易、流计算、消息推送、日志流式处理、binlog分发等场景... 查看详情

你可能需要的kafka面试题与答案整理

...一致性如何做的消息队列选型,为什么选择kafka?kafka和rocketmq吞吐量可达百万级,比activemq、rabbitmq要高一个数量级kafka和rocketmq都是分布式架构,高可用kafka和rocketmq都是毫秒级低延时,rocketmq甚至到微秒级rocketmq不支持队列层面... 查看详情

rocketmq整理(代码片段)

RocketMQ整理概念brokerMQ服务节点topic主题messagequeue消息队列,类似于kafka中的partitionproducer生产者,先去连接nameserver,查询到对应的broker信息,再去连接brokerconsumer消费者,先去连接nameserver,查询到对应的broker信息,再去连接brokern... 查看详情

kakfa从入门到放弃:kafka入门,环境搭建,命令行操作(代码片段)

...消息的软件(组件);常用的消息中间件:kafka,RabbitMQ,ActiveMQ,RocketMQ,ZeroMQ 查看详情

rocketmq高性能之底层存储设计

说在前面RocketMQ在底层存储上借鉴了Kafka,但是也有它独到的设计,本文主要关注深刻影响着RocketMQ性能的底层文件存储结构,中间会穿插一点点Kafka的东西以作为对比。例子CommitLog,一个文件集合,每个文件1G大小,存储满后存... 查看详情

mq选型对比activemq,rabbitmq,rocketmq,kafka消息队列框架选哪个?

...并发的特性,而且他的管理界面用起来十分方便。不考虑rocketmq和kafka的原因是,一方面中小型软件公司不如互联网公司,数据量没那么大,选消息中间件,应首选功能比较完备的,所以kafka排除。RocketMQ也很不错,只是没有RabbitM... 查看详情

消息队列面试题

参考技术A综上,总结如下:【activeMQ】【rabitMQ】【rocketMQ】【kafka】生产者投递消息到MQ,MQ存储消息,消费者从MQ消费消息:要分别确保上述三个过程都是成功的,有如下做法:解决方法如下:【rabbitmq解决积压范例】【kafka解决... 查看详情

rocketmq-rebalance介绍

参考技术ArocketMq概念介绍rocketMq-namesrv介绍rocketMq-Topic创建过程rocketMq-producer介绍rocketMq-consumer介绍rocketMq-rebalance介绍rocketMq-并发消费过程rocketMq-串行消费过程rocketMq-broker介绍rocketMq-broker消息存储介绍rocketMq-commitLogrocketMq-index介绍roc... 查看详情

rabbitmq,rocketmq,kafka事务性,消息丢失和重复发送处理策略

参考技术A我们的服务器从单机发展到拥有多台机器的分布式系统,各个系统之前需要借助于网络进行通信,原有单机中相对可靠的方法调用以及进程间通信方式已经没有办法使用,同时网络环境也是不稳定的,造成了我们多个... 查看详情

消息中间件如何选型

特性ActiveMQRabbitMQRocketMQKafka单机吞吐量万级,吞吐量比RocketMQ和Kafka要低了一个数量级万级,吞吐量比RocketMQ和Kafka要低了一个数量级10万级,RocketMQ也是可以支撑高吞吐的一种MQ10万级别,这是kafka最大的优点,就是吞吐量高。 ... 查看详情

阿里架构师亲授:kafka和rocketmq的消息复制实现的差异点在哪?

本文已收录GitHub,更有互联网大厂面试真题,面试攻略,高效学习资料等众所周知,消息队列在收发两端,主要是依靠业务代码,配合请求确认的机制,来保证消息不会丢失的。而在服务端,一般采用持久化和复制的方式来保证... 查看详情

如何通过 Kafka 连接器将数据从 Kafka 流式传输到 MongoDB

】如何通过Kafka连接器将数据从Kafka流式传输到MongoDB【英文标题】:HowtostreamdatafromKafkatoMongoDBbyKafkaConnector【发布时间】:2019-11-1418:11:36【问题描述】:我想使用Kafka连接器将数据从Kafka流式传输到MongoDB。我找到了这个https://github.c... 查看详情

如何配置从 kafka 到 cassandra 的 kafkaConnect

】如何配置从kafka到cassandra的kafkaConnect【英文标题】:HowtoconfigurekafkaConnectfromkafkatocassandra【发布时间】:2016-11-2404:42:51【问题描述】:我想设置从kafka主题到cassandra的kafka连接问题很简单:说我在kafka中有一个演示主题,其中包含... 查看详情