闫燕飞:Kafka的高性能揭秘及优化

2021/10/31 13:10:07

本文主要是介绍闫燕飞:Kafka的高性能揭秘及优化,对大家解决编程问题具有一定的参考价值,需要的程序猿们随着小编来一起学习吧!

大家下午好,我是来自腾讯云基础架构部ckafka团队的高级工程师闫燕飞。今天在这里首先为大家先分享一下开源Kafka在高性能上面的一些关键点,然后我会分享一下我们腾讯云ckafka对社区Kafka所做的一些优化点,最后我会介绍一下我对Kafka社区未来的展望。

Kafka高性能揭秘
在这里首先我会介绍一下整个Kafka的架构,让大家对Kafka有一个较为宏观的了解,紧接着我会在更加详细的介绍一下Kafka的存储方式以及具体消息存储格式。当然为了方便大家对kafka的高性能有个直观的理解,最后我也会给出其性能数据。

总体架构
我们可以看到Kafka整个集群里面仅仅包含了Broker,zookeeper两个组件。

Broker是整个Kafka集群的核心引擎,负责消息的存储转发,并对外提供服务。我们可以看到,Kafka集群可以非常简单的通过增删Broker,实现整个集群的扩缩容。Kafka对外提供服务的基本单位是Topic,那么实现Topic级别的平行扩展能力,也就实现了应用级的平行扩展能力。为了实现应用级的平行扩展能力,Kafka采用了对Topic进行分区的做法,通过对Topic进行分区让不同的分区落在不同的Broker上,从而利用到更多Broker的能力,最终实现了应用级的水平扩展。

Zookeeper则在整个集群中则主要负责存储一些配置信息、Broker信息、Topic信息等等元数据,并且承担了一部分协调选主的功能,可以将其理解为Kafka集群的配置管理中心。讲到这里,大家会觉得在Kafka集群中,可以简单的通过Broker动态的增删实现集群扩缩容,但在整个集群中却仅仅存在一个Zookeeper,那么Zookeeper会不会成为整个集群的瓶颈点,从而制约了整个集群的平行扩展能力?的确,在Kafka一些较老版本,Kafka的生产者及消费者都需要与Zookeeper进行通信交互,进行元数据拉取、消费分组协调、以及消费分组offset提交与保存等等。这样造成的一个问题,就是所有的客户端都要直接与ZooKeeper进行通讯交互,对其造成了非常大的压力,影响了系统的稳定性,最终影响整Kafka集群的平行扩展能力。但从0.9(含)版本之后,Kafka团队对整个Kafka进行了优化中,通过增加了一些协议,并且增加了协调模块。当前Kafka已经做到了客户端的生产及消费不需要与Zookeeper进行任何通讯交互,故Zookeeper当前仅仅充当了配置管理中心,压力非常的小,不会成为集群的瓶颈点进而制约集群的水平扩展能力。

大家也可以看到生产者及消费者是直接与Broker进行交互实现生产消费功能,Kafka在设计上并未采用传统系统中通过增加一层代理实现系统的平行扩展能力。Kafka在设计中通过内部路由协议,实现了生产者与消费者可以直接与Broker进行路由协商,从而实现了客户端直接与Broker进行生产消费,而不需要借助第三方代理。无代理的方式不仅会减少整个数据链路的长度,降低延迟,也可以提高整个系统的稳定性,而且也会节省大量的成本。

总结下Kafka的总体架构体现了如下几个主要的优势。其一,Kafka集群可以通过增删Broker实集群级的水平扩展。其二,通过对Topic进行分区,实现了应用级别的无限平行扩展能。其三,通过优良通讯协议,实现了生产系统直接与后端的Broker进行通讯,节省了代理,不仅减少了数据链路长度降低了延迟,而且极大的降低了成本。

至此,我想大家对Kafka已经有一个较为宏观了解。我们知道系统总体架构,决定了整个系统的能力上限。但系统中关键组件的性能,则是决定了相同能力下集群中服务器数量。服务器数量的增加,不仅仅会增加成本,而且会带来更多的运维压力及影响系统的稳定性。所以下面我将会介绍下Kafka核心引擎Broker的系统架构。

Broker架构
我们可以看Broker是一个典型的Reactor模型,其主要包含一个网络线程池,负责处理网络请求进行网络的收发以及打包解包,然后把请求通过请求队列推送给核心处理模块,由其负责真正的业务逻辑处理(Kafka会把所有消息落地存储,故主要是些文件I/0操作)。我们可以看到kafka采用多线程方式,可以充分利用现代系统的多核优势。其次,其采用队列方式实现了网络处理模块及核心处理模块的异步解耦,实现了网络处理和文件I/O并行处理,极大的提高了整个系统的效率。

讲到这里,大家对Kafka架构已经有一个宏观的理解。上面我们也提到,Kafka会把所有的消息都落地存储。那么为什么Kafka并未像传统的消息队列那样非常惧怕磁盘,劲量缓存而不触碰磁盘?Kafka为什么选择了将所有消息都落地存储?下面我将通过讲解其存储组织方式及存储格式,为大家进行一一揭秘。

存储的组织方式
这个就是当前Kafka的存储组织方式,我们可以看到Topic,其实只是逻辑概念,并不对应任何物理实体,为了实现Topic的水平扩展,Kafka会对其进行分区。Partition则以目录形式进行展现,同时Partition中具体的数据还未进行分片存储。这样在生产时,就能快速的找到最新的分配直接追加到文件末尾,可以看到Kafka在生产中充分利用了磁盘的顺序写,极大的提高了生产的吞吐能力。同时进行分片存储,还有一个好处就是我们可以非常方便的通过删除老的分片实现过期消息的删除。同时为了方便消费,Kafka在分片的命名上也采用了一定的技巧,分片的命名采用了其包含的第一条消息的offset进行格式化这样,在消费数据时,可以非常方便的通过二分查找定位到消息所在的文件分片。同时为了实现分片内快速定位,Kafka也会对每个数据分片建立两个稀疏索引文件,通过索引文件,采用二分查找可以非常快速的定位了指定消息在数据分片中的位置,进而进行消费。通过讲解我们可以看到Kafka的整个生产消费其实都是顺序读写,充分利用了磁盘顺序读写能力。其次,Kafka的消费,采用了二级二分查找,其查找性能仅仅依赖一个分片的索引大小,不会受整个系统数据量的影响。

Kafka处理的最基本单位是消息,那么Kafka的消息具体是什么格式?落地存储的消息又具体是什么格式?不用说这些都将极大的影响系统的性能,所以下面我也将会详细的介绍下Kafka的消息格式。

消息格式
为方便大家理解,这里我就以C代码的形式进行消息格式展示。Kafka消息其实是采用的简单的二进制编码,网络字节序存储,故可以非常高效的进行编解码操作。同时,我们可以看到整个Kafka消息头部非常的紧凑,仅仅只有30个字节左右,而且还包含了crc校验码用于对消息进行相关的校验。同时在Kafka中最为精妙的是,该消息的格式在生产系统端、网络传输中、Broker端,包括最终的文件存储中,都保持了消息格式的一致性。所以使得消息在整个系统的传输中,不需要有任何转码,效率奇高。当然为了提高整个系统的吞吐,Kafka这边实现了消息的批量生产消费。批量消息在Kafka中表现形式为,以二进制形式在内存中一个个排列起来。同时为了提高系统网络及磁盘的利用率,Kafka还是实现了消息压缩,右边这个流程图则详细的说明了消息压缩的流程。可以看到,首先我们把整个批量消息以一个整体进行压缩,生成一个新的二进制串。然后,把该值打包到一个新的消息的value字段中。可以看到Kafka非常巧妙的通过消息嵌套方式实现了消息的批量压缩,提高了整体压缩效率。同时该方式也保证了消息的格式的一致性。保持消息一致性就有以下好处:其一,我们在整个消息流转中仅仅需要生产者进行一次压缩后,将该压缩消息发送到Broker端后,Broker端仅需要一次解压操作,用以进行消息校验,并进行消息offset设置,后就能直接把消息直接存储在文件中,不需要有Broker进行一次非常消耗性能的压缩操作。所以说即使采用的消息压缩,对于Broker端的消耗也非常低。同时由于保持了压缩消息格式的一致性,当有消费请求时,Broker不用进行任何解压及压缩操作,可以直接将消息以压缩的方式发送给消费者,由消费者负责解压,这样的话Broker在整个消费中也就不需要任何的解压及压缩的操作,可以极大的提高Broker端的性能。可以看到Kafka通过这种方式,非常简单的实现了端到端的数据压缩,把计算资源消耗分摊到生产系统和消费系统中。

Kafka高性能
由于时间原因,讲到这里Kafka高性能的关键点也基本都涵盖了,当然Kafka团队为了其高性能还是有很多巧妙的设计,这里由于时间原因就不在一一赘述,当然这页PPT中则详细的列举了其高性能的关键点,大家下面有兴趣可以自己对着这些关键点自己仔细琢磨。

讲了这么多Kafka高性能的关键点,但到底其有着什么样的性能?为使大家对整个Kafka的性能有一个较为直观的认识,下面我也将给大家提出相关的性能测试数据。当然任何性能测试如果没有前置的测试条件则都是在空说,所以在给出数据前,先给一下测试的配置条件.一、测试场景是一个Broker单topic,多个partition。二、机器硬件配置是32核 64G内存,万兆网卡,同时挂载12块2T SATA盘,并且对SATA盘做了软RAID10。三、Broker版本上我们选择是0.10.2.0。Broker配置方面,我们选择的是每10万条消息或两秒进行一次刷盘。四、我们使用社区Kafka的原生压测工具,并同时开启140客户进行压测,用于模拟一定的并发。当然我后面所有压测数据都是基于这个统一的配置,后面介绍时我就不再相信叙述测试条件了。

通过下面的表格,我们可以看到Kafka在小包的情况下轻松达到百万级别的qps,而且即使在1K的大包情况下也达到了几十万级别的qps,可以说整个Kafka性能还是非常强悍的。但同时我们也发现Kafka Broker在测试中,的CPU使用率,尤其是磁盘I/O使用率并不高,说明社区Kafka还是有一定的优化空间。所以下面我就介绍一下我们CKafka对社区Kafka的一些优化点。

Kafka性能优化
在这个章节里面,首先我会带领大家进一步的深入了解一下整个 Broker端的架构,通过进一步了解他的架构,找出它可能的瓶颈点,然后在针对瓶颈点进行优化优化。紧接着我将会挑出几个具体的优化点进行详细的介绍。

当前架构剖析
在这里为了方便大家理解,我们用一次真实的请求,经过的路径,来说明Broker各个模块是怎么交互的。首先,当一个生产启动,他需要去和Broker进行连接,Broker端会有一个Accept线程模块进行连接监听用于建立新的连接,在连接建立后Accept会将网络连接轮询转发给给网络接收发送处理线程池中的一个线程处理,至此连接接入已经完成。下面将进入数据请求,这时候生产者发送的生产请求数据,将直接由网络收发处理线程进行处理,每当网络线程收到一个完整的包,并进完成解包操作后,就会将请求推送到请求队列,由后端核心处理线程进行真正的逻辑处理。后端核心I/O处理线程会竞争的从请求队列中拉取到生产请求任务后,首先,其会对相应的消息进行解析,创建相应的消息对象,然后消息对象进行一些合法性校验,并设置相应的offset,当完成这些后会将消息写入文件。当然写入完成后会检测未刷盘的消息个数是否达到刷盘要求,如果达到刷盘要求,该线程还会主动进行刷盘操作,最后把这个处理结果通过每个网络处理线程的应答队列,返回给对应的网络处理线程,最后由网络线程进行打包并把结果返回给生产端,至此一个生产流程就以完成。

在这个流程中,我们可以发现:一、在整个Kafka的架构中,仅仅只有一个请求队列,而且该队列还未进行任何无锁化优化,这样会导致网络处理线程池以及核心I/O处理线程产生激烈的锁竞争,从而有可能影响整个系统的并发性,进而影响到系统的性能。所以这个是我们应该想到一个优化点。其二,我们刚才讲到Kafka选择直接在核心处线程中直接进行磁盘刷盘,这样会导致堵塞整个核心流程,进而影响整个系统的性能。这也是我们今天发现的需要优化的第二个一个优化点。其三,就是我们发现在生产消息中会生成大量的消息对象,用于进行消息的合法性的校验。产生大量的消息对象,会对jvm的GC产生较大的影响,可能会成为系统性能的瓶颈点。当然我们ckafka对社区kafka还做了很多其它方面的优化,这里有由于时间关系,主要集中这三点进行介绍。

锁优化
我们第一版的锁优化,通过架构图可以看到,其实是非常简单的。我们直接把broker端仅有的一个请求队列,替换成一个无锁请求队列,当然我们也对所有的应答队列进行了无锁队列的替换优化。富贵论坛经过这一轮优化,我们具体到达成一个什么效果?这个就是当前无锁队列的优化结果。通过对比我们可以发现,经过无锁队列优化后,相对于社区版本Kafka,整个性能基本上保持了一致。但按照我们之前的分析,按理说应该会有较大的性能提升才对,但为啥没有达到预期效果?

为一探究竟,我们又对 Broker进行了更为详细的统计分析。通过统计分析后,我们统计了请求次数,通过下面的统计图表,我们发现不管是社区Kafka,还是我们优化的版本,即使在百万qps的消息情况下,生产请求个数都非常的少,都是在10w级别以下。讲到这里我们明白了,正是由于开源Kafka这边采用了批量发送的方式,合并了大量的生产请求,使的整个Broker端的请求次数急剧的减少,请求量的减少就使得网络处理线程及核心处理线程间的锁争用减少,在当前请求量级的情况下锁争用不太会成为真个系统的瓶颈点,所以我们的无锁队列没有达到理想的效果也是正常的。讲到这里,可以说我们第一个优化其实是不太成功的,但是优化道路总是漫长曲折的,一次不成功也正常也不会吓到我们,我们ckafka会持续不但的在优化道路上前行。

文件刷盘优化
下面我们进行第二个优化点的介绍,异步刷盘优化。在异步刷盘优化方面,我们ckafka专门增加了一组刷盘线程,专门用于磁盘刷盘,这样当核心线程发现需要有刷盘需要时,直接生成一个刷盘任务,并将刷盘任务通过无锁队列推送给刷盘线程,由其进行刷盘即可。这样的话我们就可以实现在刷盘时不堵塞核心处理线程处理,会极大的提高一个系统的性能。当然经过这一轮的话后我们到底有没有效果?具体我们看一下下面的性能对比数据。

经过异步刷盘优化后,我们可以看到,优化后的吞吐在小包情况下,较社区版本有4到5倍的性能提升,同时即使是在大包情况下也有一倍左右的性能提升(随着包的增大及partition的增多优化后的提升会成下降趋势)。同时我们可以发现在我们异步刷盘优化的测试过程中,整个系统的I/O使用率已经非常搞了,基本都在90%以上了,可以说现在整个系统的瓶颈点应该就是磁盘I/O了,同时超过90%的I/O使用率,说明我们已经榨干了系统磁盘的性能,也表示我们后续的吞吐量优化空间已经不大了。那么这样是不是说我们整个Kafka就没有任何的优化空间了?其实对于系统的优化则不仅仅是包含了吞吐量的提升,我们还可以从相同吞吐量下资源使用率方面进行相关的优化,所以ckafka对社区Kafka的优化并未止步于当前,所以我们进一步进行了下一个GC方面的优化。我们期望通过该优化不仅能有吞吐方面的提升,更重要的是期望在类似的场景下,可以更好的减少资源的使用率,进一步缩减成本。

GC优化
在GC优化方面,主要是社区Kafka在对生产消息进行校验时会针对每条消息生成一个消息对象,导致产生大量的消息对象,ckafka通过优化,采用直接在ByteBuffer二进制数据上进行消息校验,这样在整个消息校验中就不会生成任何消息对象,减少大量的消息对象的生成,则会降低对jvm GC的压力,进而提高系统的性能。通过对比优化前后的性能数据,我们可以看到它起到一定效果的。我们可以看到优化后整个GC的耗时占比的已经低于2.5%,可以说GC已经不会成为系统的瓶颈点了。我们看一下社区开源Kakfa这边的GC耗时,在较多的partition较小的消息下,直接可以达到10%的消耗。通过我们的GC优化后,可以看到整个GC耗时方面的话,有1.5%到7%的性能的提高。同样我们可以看到,在吞吐量差不多的情况下,我们整个系CPU消耗较交社区版的CPU有关5%到10%的降低,所以可以肯定的说GC优化有效的降低了系统CPU资源的消耗,起到一定的效果。最后我们发现整个GC优化前后系统中I/O基本上已经达到顶点,已经成为系统的瓶颈点,所以GC优化就和前面预测的一致并未有吞吐量大幅的提升,主要集中在降低系统资源的消耗,对于前端客户端来说则是一定幅度上降低系统的延迟。

至此由于时间原因,Kafka的性能优化的介绍已经完毕。但为了更加方便大家直观的理解,这一页PPT则贴出了最终的优化对比效果。我们来看看最终优化后的效果,可以看出我们最终完整版优化,在小包情况下有4到5倍的性能提升,即使在1K的大包情况下,也有一倍左右的性能提升(当然随着partition的增加及消息大小的增加,优化效果呈一定的下降趋势)。同时我们可以发现整个系统的I/O已经是成为系统的瓶颈点。也为我们后面系统硬件选择方面提供一个参考,可能我们后面会通过挂载更多的磁盘,进一步提高系统的吞吐压榨系统的性能,进一步平衡CPU及磁盘的配比消耗,当然通过选择更合适的硬件做到CPU、磁盘、网络之间合适的配比实现资源利用的更大化。

下面我讲一下我们在CKafka运营中所发现一些问题,以及我们针对这些问题的优化点,同时我们期望社区Kafka能够采纳我们ckafka在运营中发现并优化的一些关键点建议,让kafka能够更好的适应生产条件。

其一,当前社区Kafka还无法采用pipe方式进行消费,这样就导致出现以下几个问题:一、消费者的性能非常依赖于与Broker端的网络延迟,当消费者与Broker存在跨城区的时候,由于网络延迟的增大,会导致整个消费性能非常低下,这样就最终限制了Kafka的使用场景,使其不能很好的作用于跨城区数据同步,限制了其使用的场景。二,Kafka在副本复制的时复用了消费逻辑,同样走的也是消费者逻辑,这样也同样导致其无法使用pipe方式,最后导致了副本同步性能低下而且非常依赖于延迟,最终导致了整个Kafka集群不太可能进行一些跨区域的部署,限制了Kafka部署的灵活性,而且同时在压力较大的情况下,容易出现副本拉取的速度跟不上生产的速度导致ISR抖动影响系统性能。针对这个问题,其实在第二点,我们这边已经做了优化,使得副本拉取已经可以进行pipe方式,后面即使需要做一些跨城区部署,其整个副本同步性能是能够达到要求的。但是在这里第一个问题我们这里无法解决,因为我们这边生为了兼容性社区版本Kafka,是让客户直接采用的是开源的SDK,导致了我们这里还没法没办法优化。在这里我希望社区Kafka,可以采纳相关的建议,实现消费者pipe方式,使得整个消费性能不在依赖于网络延迟,使得用户的使用上没有地域空间的一些限制。

其二,就是当前社区Kafka对消费为了性能方面的考虑,他在设计中是不支持低版本的消费者直接去消费高版本生产增产的消息,而当前Kafka发展到现在已经有三个消息版本,这样就导致了业务的在使用Kafka时,包括生产者及消费者的升级降级都是非常不友好的。当然这里我们在进行云化的时候,我们已经实现了对消息格式转换,已经实现了不同版本消息混合存储在同一个文件中,已经实现了任意版本的生产以及任意版本的消费。这里我们希望社区Kafka能否试试放开相关的支持,因为毕竟在生产系统中,业务使用时兼容性是最重要的考量标准之一。而且即使是我们现在的实现存在消息高低版本的转码,其实CPU现在还是有富余的,也不是系统的瓶颈点,所以说我希望社区这边能够采纳

讲到这里,其实我的分享也基本上完了。然后这是我的个人微信,大家如果有什么问题可以加我的微信。当然,现在我们的CKafka团队也在大量的招人,大家有意向的话也可以联系我们。

Q/A
Q:这里需要请教你一个问题,就是我看刚才看到一部刷盘优化的时候,发现CPU也是随着性能的提升上升了很多倍,这里是不是主要是因为优化过程中你又做了一次拷贝?

A:没有,其实社区Kafka在内存拷贝方面还是有一些优化的。唉,稍等一下,社区Kafka在整个消息流转中,比如生产消息时,他从网络层开始会生成一个ByteBuffer用于存储消息包,而后这个ByteBuffer会在整个系统中不断的扭转,它是不会有新的拷贝的,除非有一些消息需要有不同方式的存储时,需要有转码的要求,他才会生成一个新的消息进行一次内存拷贝否则不会有多次内存拷贝。而我们这里在做异步刷盘优化时,其实是不会有任何多于的内存拷贝的,我们的CPU使用有数倍的提高,主要还是在与吞吐的提高,可以看到我们系统在小包情况下有4 ~ 5倍的性能提升,这样提升,会导致更多的网络操作,更多的打包解包,更多的系统I/O当然最终就会导致更多的cpu,当然就会需要更多的CPU消耗。这么多消耗的叠加当然照成CPU使用率数倍的提高也是很正常的。

Q:我有个问题想问一下你刚才之前PPT也有说就是说在系统量很大的情况下,副本的拉取速率无法跟上生产的速率,对这个的话我们测试或者是说线上其实也会碰到副本拉取跟不上生产速度,而且会影响导致其它节点也跟不上,照成一种雪崩效应。然后我想问一下你这边的解决办法,你刚才说有解决办法,我想问一下你们这边是采用哪种解决办法?

A: 社区Kafka副本拉取不上最主要的原因,是因为采用了消费方式,但消费方式又不支持pipe方式消费。其实Kafka的副本拉取是同步方式,发送一个副本拉取请求后等到应答后再次发送一次同步拉取请求,无法使用pipe流水线方式,这样的同步方式Broker的网络延迟会成为整个副本同步的关键点,并且在压力大的情况下整个Kakfa的broker端出来延迟会达到秒及,这样会导致整个副本拉取性能不足,不足的真正原因就是拉取请求次数不够,如果我们采用pipe方式增大拉取请求次数,自然也就增大了副本同步的性能。

Q:你们还有没有就是说更具体一点的解决方式?

主要是我们这边的话,副本的同步采用了一个新的协议,使的副本拉取请求可以采用pipe方式增大请求次数进而提高副本同步速度。其实,社区Kafka副本拉取跟不上的真正原因是应为请求都是同步的,延迟正大导致请求量减少,请求量的减少最终导致副本性能下降导致无法跟上,所以我们所要做的就是加大副本同步请求个数,就可以从根本上解决问题,我们这里采用的就是pipe方式,用于增大请求次数解决副本无法跟上的问题。这其实是最核心的,也是最简单一个解决方案了。

Q: 请问一下就是说我刚才看到有一个异步落盘的优化,问一下就是说你这里公布的数据都是没有时延信息的,我不知道就是说这个有话会不会导致业务时延增加。

A: 因为测试中客户端比较多,统计上加上时延就会导致更加的杂乱,故这里统计数据并未有展示出来,其实我们测试统计中采用异步刷盘后这个时延效果其实更好。因为采用异步刷盘后在整个请求中不会堵塞任何核心流程,只用把刷盘任务推送到队列,就可以直接返回给前端客户端了。但是如果你不使用异步刷盘直接在核心流程中进行刷盘的话,会堵塞核心流程的,而且每次刷盘耗时其实是非常大的,经常会到达400毫秒左右的延迟,所以延迟会更大。采用异步刷盘后,经过我们测试,即使在七八百MB的最高吞吐下,我们这边整个延迟是保持得非常好,整个测试的平均延迟是在15毫秒到30毫秒之间。然而在社区Kafka环境下,其延迟其实是在200毫秒左右。

Q: 我就问,如果异步落盘的时候,它到期还没刷到盘,这个不需要等到刷盘完成后才返回给客户吗?会不会导致未刷盘时消息丢失?

A: 这个其实和Kafka的应用场景有关了,当前社区Kafka也不是每条消息都刷盘,其实刷盘也是通过配置一个消息间隔数或间隔时间进行的,这样其实社区Kafka这边在系统掉电的情况下,是还真的没法保证这个消息不丢失。Kafka应用场景一般也不是在用在完全不需要消息丢失的场景,而是主要用于一些日志采集等实时性要求比较高,吞吐要求比较高的场景,Kafka这里为了吞吐这边其实还是选择了牺牲一定的消息的可靠性的。当然针对我们这个异步刷盘,当前的第一步优化比较简单,我们直接把任务推送到刷盘人群队列,就返回给客户端成功,的确会导致一部分消息在系统掉电下导致丢失。当前为了切合Kafka的应用场景,采用了优先吞吐的方式,当然,我们后面还会根据需要看看,是否需要实现真正刷盘后在返回给用户成功。其实实现这个也比较简单,我们选择挂起生产请求,直到刷盘线程真正刷盘后,在返回给客户成功即可。但这样的话你刚才也说了可能会导致的延迟增大,因为你必须要等它真正的刷盘完成,这个可能需要你自己根据应用形态采用而不同的方式,实现一个高吞吐及高可靠的一个取舍了。

Q:你好,问个问题就是两个问题,第一个问题是关于数落盘的,因为刚才也提到说Kafka里面的数据不一定是可靠的,然后想问一下腾讯在这边对数据可靠性是有做了什么优化和方案这样。

A:一方面,从硬件方面,其实我们这里所有的存储磁盘,都采用了RAID10的方式,这样即使有少量的磁盘的损坏,对我们来说的话是不会有数据丢失的风险的。另一方面,ckafka和社区kafka一样都可以通过多副本的方式,加上一定合理的配置,可以保证在机器损坏时,数据不丢失。再次,在实现上我们ckafka也做到了定时定量进行主动刷盘可以降低机器由于意外掉电导致的数据丢失。所以相对应社区kafka ckafka从硬件及软件上都有更高的数据可靠性保证。

Q:然后第二个问题,刚才说到说跨城区的副本同步就有个问题,现在腾讯这边的部署是跨城区部署的吗?

A:当前ckafka的部署采用的是同城区,同zone部署的,但是我们ckafka是可以实现跨城区部署的,当前没提供这种部署方式,最主要的原因是当前使用社区Kafka sdk的消费者性能强依赖于与Broker之间网络延迟。如果我们进行跨地域部署的话,那么客户端的消费性能是得不到保障的,因为不通地域之间的网络延迟往往都在几十毫秒,甚至上百毫秒,这样使得整个消费性能下降非常严重无法满足业务的需求。当然如果社区Kafka SDK能够采用我们上面的建议实现消费者pipe方式消费,那么进行跨地域部署将不会有任何问题。

Q:OK带来另外一个问题,就是我觉的如果真的出现意外情况,比如像天津大爆炸案,导致整个腾讯的天津机房都炸掉了,你们这里的话有没有考虑过这种迁移计划?

A:其实我们ckafka是在各个地域都部署的有相关的集群,用户可以通过在不同地域购买不同的实例,一方面实现就近接入,另一方面实现异地容灾,保证程序的可用性。当然用户也可以通过,我们提供的Kafka的一些同步工具,进行数据在不同地域间同步,用于实现地域级别的容灾。

Q:对于业务来说,如果他使用同步工具那么会不会对业务照成更大的成本?业务是否需要改造相关的程序用以实现跨城区访问?

A:对业务使用方来说,可以直接使用一些开源的工具及方法,用户是不需要有任何的更改就能实现跨地域访问,社区Kafka的生态及工具还是比较完善的大家可以多去社区上逛逛总能找到适合自己的工具。



这篇关于闫燕飞:Kafka的高性能揭秘及优化的文章就介绍到这儿,希望我们推荐的文章对大家有所帮助,也希望大家多多支持为之网!


扫一扫关注最新编程教程