0
  • 聊天消息
  • 系统消息
  • 评论与回复
登录后你可以
  • 下载海量资料
  • 学习在线课程
  • 观看技术视频
  • 写文章/发帖/加入社区
会员中心
创作中心

完善资料让更多小伙伴认识你,还能领取20积分哦,立即完善>

3天内不再提示

Kafka高性能背后的技术原理

小林coding 来源:君哥聊技术 2024-10-23 09:37 次阅读

以下文章来源于君哥聊技术,作者朱晋君

Kafka 是一款性能非常优秀的消息队列,每秒处理的消息体量可以达到千万级别。

今天来聊一聊 Kafka 高性能背后的技术原理,也是面试常问的一个知识考点。

1 批量发送

Kafka 收发消息都是批量进行处理的。我们看一下 Kafka 生产者发送消息的代码:

privateFuturedoSend(ProducerRecordrecord,Callbackcallback){
TopicPartitiontp=null;
try{
//省略前面代码
CallbackinterceptCallback=newInterceptorCallback<>(callback,this.interceptors,tp);
//把消息追加到之前缓存的这一批消息上
RecordAccumulator.RecordAppendResultresult=accumulator.append(tp,timestamp,serializedKey,
serializedValue,headers,interceptCallback,remainingWaitMs);
//积累到设置的缓存大小,则发送出去
if(result.batchIsFull||result.newBatchCreated){
log.trace("Wakingupthesendersincetopic{}partition{}iseitherfullorgettinganewbatch",record.topic(),partition);
this.sender.wakeup();
}
returnresult.future;
//handlingexceptionsandrecordtheerrors;
//forAPIexceptionsreturntheminthefuture,
//forotherexceptionsthrowdirectly
}catch/**省略catch代码*/
}

从代码中可以看到,生产者调用 doSend 方法后,并不会直接把消息发送出去,而是把消息缓存起来,缓存消息量达到配置的批量大小后,才会发送出去。

注意:从上面 accumulator.append 代码可以看到,一批消息属于同一个 topic 下面的同一个 partition。

Broker 收到消息后,并不会把批量消息解析成单条消息后落盘,而是作为批量消息进行落盘,同时也会把批量消息直接同步给其他副本。

消费者拉取消息,也不会按照单条进行拉取,而是按照批量进行拉取,拉取到一批消息后,再解析成单条消息进行消费。

使用批量收发消息,减轻了客户端和 Broker 的交互次数,提升了 Broker 处理能力。

2 消息压缩

如果消息体比较大,Kafka 消息吞吐量要达到千万级别,网卡支持的网络传输带宽会是一个瓶颈。Kafka 的解决方案是消息压缩。发送消息时,如果增加参数 compression.type,就可以开启消息压缩:

publicstaticvoidmain(String[]args){
Propertiesprops=newProperties();
props.put("bootstrap.servers","localhost:9092");
props.put("key.serializer","org.apache.kafka.common.serialization.StringSerializer");
props.put("value.serializer","org.apache.kafka.common.serialization.StringSerializer");
//开启消息压缩
props.put("compression.type","gzip");
Producerproducer=newKafkaProducer<>(props);

ProducerRecordrecord=newProducerRecord<>("my_topic","key1","value1");

producer.send(record,newCallback(){
@Override
publicvoidonCompletion(RecordMetadatametadata,Exceptionexception){
if(exception!=null){
logger.error("sendingmessage error:", e);
}else{
logger.info("sendingmessage successful, Offset:", metadata.offset());
}
}
});

producer.close();
}

如果 compression.type 的值设置为 none,则不开启压缩。那消息是在什么时候进行压缩呢?前面提到过,生产者缓存一批消息后才会发送,在发送这批消息之前就会进行压缩,代码如下:

publicRecordAppendResultappend(TopicPartitiontp,
longtimestamp,
byte[]key,
byte[]value,
Header[]headers,
Callbackcallback,
longmaxTimeToBlock)throwsInterruptedException{
//...
try{
//...
buffer=free.allocate(size,maxTimeToBlock);
synchronized(dq){
//...
RecordAppendResultappendResult=tryAppend(timestamp,key,value,headers,callback,dq);
if(appendResult!=null){
//Somebodyelsefoundusabatch,returntheonewewaitedfor!Hopefullythisdoesn'thappenoften...
returnappendResult;
}
//这批消息缓存已满,这里进行压缩
MemoryRecordsBuilderrecordsBuilder=recordsBuilder(buffer,maxUsableMagic);
ProducerBatchbatch=newProducerBatch(tp,recordsBuilder,time.milliseconds());
FutureRecordMetadatafuture=Utils.notNull(batch.tryAppend(timestamp,key,value,headers,callback,time.milliseconds()));

dq.addLast(batch);
incomplete.add(batch);

//Don'tdeallocatethisbufferinthefinallyblockasit'sbeingusedintherecordbatch
buffer=null;

returnnewRecordAppendResult(future,dq.size()>1||batch.isFull(),true);
}
}finally{
if(buffer!=null)
free.deallocate(buffer);
appendsInProgress.decrementAndGet();
}
}

上面的 recordsBuilder 方法最终调用了下面 MemoryRecordsBuilder 的构造方法。

publicMemoryRecordsBuilder(ByteBufferOutputStreambufferStream,
bytemagic,
CompressionTypecompressionType,
TimestampTypetimestampType,
longbaseOffset,
longlogAppendTime,
longproducerId,
shortproducerEpoch,
intbaseSequence,
booleanisTransactional,
booleanisControlBatch,
intpartitionLeaderEpoch,
intwriteLimit){
//省略其他代码
this.appendStream=newDataOutputStream(compressionType.wrapForOutput(this.bufferStream,magic));
}

上面的 wrapForOutput 方法会根据配置的压缩算法进行压缩或者选择不压缩。目前 Kafka 支持的压缩算法包括:gzip、snappy、lz4,从 2.1.0 版本开始,Kafka 支持 Zstandard 算法。

在 Broker 端,会解压 header 做一些校验,但不会解压消息体。消息体的解压是在消费端,消费者拉取到一批消息后,首先会进行解压,然后进行消息处理。

因为压缩和解压都是耗费 CPU 的操作,所以在开启消息压缩时,也要考虑生产者和消费者的 CPU 资源情况。

有了消息批量收集和压缩,kafka 生产者发送消息的过程如下图:

33f1d514-90dd-11ef-a511-92fbcf53809c.png

3 磁盘顺序读写

顺序读写省去了寻址的时间,只要一次寻址,就可以连续读写。

在固态硬盘上,顺序读写的性能是随机读写的好几倍。而在机械硬盘上,寻址时需要移动磁头,这个机械运动会花费很多时间,因此机械硬盘的顺序读写性能是随机读写的几十倍。

Kafka 的 Broker 在写消息数据时,首先为每个 Partition 创建一个文件,然后把数据顺序地追加到该文件对应的磁盘空间中,如果这个文件写满了,就再创建一个新文件继续追加写。这样大大减少了寻址时间,提高了读写性能。

4 PageCache

Linux 系统中,所有文件 IO 操作都要通过 PageCache,PageCache 是磁盘文件在内存中建立的缓存。当应用程序读写文件时,并不会直接读写磁盘上的文件,而是操作 PageCache。

33fa2b24-90dd-11ef-a511-92fbcf53809c.png

应用程序写文件时,都先会把数据写入 PageCache,然后操作系统定期地将 PageCache 的数据写到磁盘上。如下图:

34021e6a-90dd-11ef-a511-92fbcf53809c.png

而应用程序在读取文件数据时,首先会判断数据是否在 PageCache 中,如果在则直接读取,如果不在,则读取磁盘,并且将数据缓存到 PageCache。

3409b486-90dd-11ef-a511-92fbcf53809c.png

Kafka 充分利用了 PageCache 的优势,当生产者生产消息的速率和消费者消费消息的速率差不多时,Kafka 基本可以不用落盘就能完成消息的传输。

5 零拷贝

Kafka Broker 将消息发送给消费端时,即使命中了 PageCache,也需要将 PageCache 中的数据先复制到应用程序的内存空间,然后从应用程序的内存空间复制到 Socket 缓存区,将数据发送出去。如下图:

341c0708-90dd-11ef-a511-92fbcf53809c.png

Kafka 采用了零拷贝技术把数据直接从 PageCache 复制到 Socket 缓冲区中,这样数据不用复制到用户态的内存空间,同时 DMA 控制器直接完成数据复制,不需要 CPU 参与。如下图:

34240c00-90dd-11ef-a511-92fbcf53809c.png

Java 零拷贝技术采用 FileChannel.transferTo() 方法,底层调用了 sendfile 方法。

6 mmap

Kafka 的日志文件分为数据文件(.log)和索引文件(.index),Kafka 为了提高索引文件的读取性能,对索引文件采用了 mmap 内存映射,将索引文件映射到进程的内存空间,这样读取索引文件就不需要从磁盘进行读取。如下图:

3440d9d4-90dd-11ef-a511-92fbcf53809c.png

7 总结

本文介绍了 Kafka 实现高性能用到的关键技术,这些技术可以为我们学习和工作提供参考。

声明:本文内容及配图由入驻作者撰写或者入驻合作网站授权转载。文章观点仅代表作者本人,不代表电子发烧友网立场。文章及其配图仅供工程师学习之用,如有内容侵权或者其他违规问题,请联系本站处理。 举报投诉
  • 代码
    +关注

    关注

    30

    文章

    4696

    浏览量

    68083
  • 消息队列
    +关注

    关注

    0

    文章

    33

    浏览量

    2958
  • kafka
    +关注

    关注

    0

    文章

    50

    浏览量

    5200

原文标题:面试官:你说说 Kafka 为什么是高性能的?

文章出处:【微信号:小林coding,微信公众号:小林coding】欢迎添加关注!文章转载请注明出处。

收藏 人收藏

    评论

    相关推荐

    泰克30+GHz高性能示波器的关键技术

    泰克公司最近宣布首款经验证采用 IBM 8HP 硅锗 (SiGe) BiCMOS 特殊工艺技术设计的新型示波器平台ASIC各项技术指标优于规定要求,实现了新型高性能示波器的设计目标,使多通道带宽达
    发表于 07-24 07:47

    基于闪存存储的Apache Kafka性能提升方法

    作者:Dennis Lattka我是美光科技的首席存储解决方案工程师Dennis Lattka。这个头衔的真正含义是,我要致力于确定如何利用闪存存储改善工作负载应用的性能和结果。为此,我决定对大数
    发表于 07-24 06:58

    浅析kafka

    kafka常见问题
    发表于 09-29 10:09

    基于发布与订阅的消息系统Kafka

    Kafka权威指南》——初识 Kafka
    发表于 03-05 13:46

    Kafka基础入门文档

    kafka系统入门教程(原理、配置、集群搭建、Java应用、Kafka-manager)
    发表于 03-12 07:22

    Kafka集群环境的搭建

    1、环境版本版本:kafka2.11,zookeeper3.4注意:这里zookeeper3.4也是基于集群模式部署。2、解压重命名tar -zxvf
    发表于 01-05 17:55

    Kafka文件存储机制分析

    机制设计是衡量一个消息队列服务技术水平和最关键指标之一。 《br》 下面将从Kafka文件存储机制和物理结
    发表于 09-28 15:40 0次下载

    大数据开发最火技术Kafka背后的“黑科技”

    、低延迟等方面有很突出的表现。这篇文章不同于其他介绍Kafka使用或实现的文章,只是谈谈Kafka用了什么“黑科技”使他在性能方面有这么突出的表现。消息顺序写入磁盘磁盘大多数都还是机械结构(SSD不在
    的头像 发表于 10-22 17:53 949次阅读
    大数据开发最火<b class='flag-5'>技术</b><b class='flag-5'>Kafka</b><b class='flag-5'>背后</b>的“黑科技”

    Kafka的概念及Kafka的宕机

    问题要从一次Kafka的宕机开始说起。 笔者所在的是一家金融科技公司,但公司内部并没有采用在金融支付领域更为流行的 RabbitMQ ,而是采用了设计之初就为日志处理而生的 Kafka ,所以我一直
    的头像 发表于 08-27 11:21 2015次阅读
    <b class='flag-5'>Kafka</b>的概念及<b class='flag-5'>Kafka</b>的宕机

    Kafka如何做到那么高的性能

    有人说:他曾在一台配置较好的机子上对 Kafka 进行性能压测,压测结果是 Kafka 单个节点的极限处理能力接近每秒 2000万 条消息,吞吐量达到每秒 600MB。
    的头像 发表于 09-14 17:03 976次阅读

    Kafka 的简介

    ,即使对TB级以上数据也能保证常数时间的访问性能 高吞吐率。即使在非常廉价的机器上也能做到单机支持每秒100K条消息的传输 支持Kafka Server间的消息分区,及分布式消费,同时保证每个
    的头像 发表于 07-03 11:10 553次阅读
    <b class='flag-5'>Kafka</b> 的简介

    物通博联5G-kafka工业网关实现kafka协议对接到云平台

    Kafka协议是一种基于TCP层的网络协议,用于在分布式消息传递系统Apache Kafka中发送和接收消息。Kafka协议定义了客户端和服务器之间的通信方式和数据格式,允许客户端发送消息到K
    的头像 发表于 07-11 10:44 455次阅读

    Kafka中学习高性能系统如何设计

    相信各位小伙伴之前或多或少接触过消息队列,比较知名的包含 Rocket MQ 和 Kafka,在京东内部使用的是自研的消息中间件 JMQ,从 JMQ2 升级到 JMQ4 的也是带来了性能上的明显提升,并且 JMQ4 的底层也是参考 Ka
    的头像 发表于 07-17 11:25 525次阅读
    从<b class='flag-5'>Kafka</b>中学习<b class='flag-5'>高性能</b>系统如何设计

    Kafka架构技术Kafka的架构和客户端API设计

    Kafka 给自己的定位是事件流平台(event stream platform)。因此在消息队列中经常使用的 "消息"一词,在 Kafka 中被称为 "事件"。
    的头像 发表于 10-10 15:41 2242次阅读
    <b class='flag-5'>Kafka</b>架构<b class='flag-5'>技术</b>:<b class='flag-5'>Kafka</b>的架构和客户端API设计

    golang中使用kafka的综合指南

    kafka是一个比较流行的分布式、可拓展、高性能、可靠的流处理平台。在处理kafka的数据时,这里有确保处理效率和可靠性的多种最佳实践。本文将介绍这几种实践方式,并通过sarama实现他们。
    的头像 发表于 11-30 11:18 508次阅读