当前位置: 首页 > article >正文

Kafka为什么快(高性能的原因)

我们知道,Kafka 是基于磁盘存储的,但它却又具有高性能、高吞吐、低延时等特点,吞吐量可达几十上百万。那么 Kafka 这么快的原因是什么呢?

Kafka 高性能主要取决于以下几方面:
(1)消息批处理+压缩传输
(2)顺序写磁盘 + PageCache
(3)零拷贝技术
(4)分区分段+索引

 

1、消息批处理及压缩传输
(1)批处理
Kafka内部,消息都是以“批”为单位处理的,Kafka的客户端SDK在实现消息发送逻辑的时候,采用了异步批量发送的机制。

当调用 send() 方法发送一条消息后,无论是同步还是异步发送,Kafka 并不会立刻将该条消息发出去,它会先把它存在内存,然后选择合适的时机(涉及两个参数)把缓存的所有消息组成一批,一次性的发给Broker。

Broker端在数据处理过程中,无论是写磁盘、读磁盘读出来、还是复制消息到其他副本,都是以批进行(批不会被解开为一条一条消息)处理的。

消费时,消息同样是以批为单位,Consumer 从 Broker 拉到一批消息后,在客户端把批消息解开,再一条条的交给用户代码处理。

由此,构建和解开批消息分别在发送端和消费端的客户端完成,减轻了 Broker 的压力,也减少了 Broker 处理请求的次数,提升了整体的吞吐能力。

producer 端涉及两个批处理参数:
batch.size:消息条数积累到该阈值,立即发送.
linger.ms:不管消息有没有积累足够条数,超过该时间就立即发送

(2)压缩传输
默认情况下,在 Kafka 生产者中不启用消息压缩(compression.type参数来控制压缩方式)。因为压缩虽然可以减少网络带宽消耗和存储空间,但也会增加 CPU 的负担。

在 Kafka 中,压缩可能会发生在两个地方:生产者端和 Broker 端,一句话总结下压缩和解压缩,即 Producer 端压缩,Broker 端保持,Consumer 端解压缩。

Kafka 支持多种压缩算法:lz4、snappy、gzip,从 Kafka 2.1.0 开始新增了 ZStandard 算法,该算法是 Facebook 开源的压缩算法,能提供超高的压缩比。

Producer、Broker、Consumer 要使用相同的压缩算法,在 Producer 向 Broker 写入数据,Consumer 向 Broker 读取数据的时候可以不用解压缩,只需要在最终 Consumer 到消息的时候才进行解压缩,这样可以节省大量的网络和磁盘开销。

 
2、顺序写磁盘 + PageCache
Kafka 为了保证磁盘写入性能,通过基于操作系统的页缓存来实现文件写入的。操作系统本身有一层缓存,叫做 page cache,是在内存里的缓存,也可以称之为 os cache,意思就是操作系统自己管理的缓存。那么在写磁盘文件的时候,就可以先直接写入 os cache 中,也就是仅写入内存中,接下来由操作系统自己决定什么时候把 os cache 里的数据真正刷入到磁盘,这样大大提高写入效率和性能。

另外还有个关键操作,就是 kafka 在写数据的时候是以磁盘顺序写的方式来进行落盘的,即将数据追加到文件的末尾,而不是在文件的随机位置来修改数据,对于普通机械磁盘,如果是随机写的话,涉及到磁盘寻址的问题,导致性能极低,但是如果只是按照顺序的方式追加文件末尾的话,这种磁盘顺序写的性能基本可以跟写内存的性能相差无几。

 
3、零拷贝技术
(1)传统拷贝流程
在这里插入图片描述

流程步骤:
(1)操作系统将数据从磁盘文件中读取到内核空间的页面缓存;
(2)应用程序将数据从内核空间读入用户空间缓冲区;
(3)应用程序将读到数据写回内核空间放入 socket 缓冲区;
(4)操作系统将数据从 socket 缓冲区复制到网卡接口,然后数据通过网络发送。

可以看出,上述过程涉及到 4 次数据的复制,并且有两次复制操作是由 CPU 完成。但这个过程中,数据完全没有变化,仅仅是从磁盘复制到网卡缓冲区。

 
(2)零拷贝流程
在这里插入图片描述

 

可以看到,使用零拷贝技术把上面第2、3步的两次复制合并成一次。直接从 PageCache 中将数据复制到 Socket 缓冲区,这不仅减少了复制次数,且由于不用把数据复制到用户内存空间,DMA 控制器就可以直接完成数据复制,不需要CPU 的参与,速度更快。

 
4、分区分段 + 索引
Kafka 中的消息是按 topic 分类存储的,topic 中的数据又是按照一个一个分区(partition)存储到不同的 broker 节点上。每个 partition 对应操作系统上的一个文件夹,每个 partition 数据是以追加方式写入到一个有序的日志文件中。

这个日志文件实际上是由多个日志段(segment)文件组成。
每个 segment 文件都是一个独立的文件,它包含一定数量的消息。随着新消息不断追加,旧的 segment 文件会根据清理策略最终被删除。
 

在这里插入图片描述
 

通过这种分区分段的设计,Kafka 的消息最终相当于是分布式存储在一个个小的 segment 中,每次文件操作也是直接操作 segment。

同时,为了进一步的查询优化,Kafka 又默认为分段后的数据文件建立了索引文件(index文件)。通过索引文件,Kafka 可以快速定位特定偏移量的消息,而不需要遍历整个日志。

这种分区分段+索引的设计,不仅提升了数据读取的效率,同时也提高了数据操作的并行度。

 
 
 
 
 
 

大佬,点个赞再走呗!

 

在这里插入图片描述


http://www.kler.cn/a/466262.html

相关文章:

  • Qt 5.14.2 学习记录 —— 일 新项目
  • 类的定义和使用(python)
  • 【信息系统项目管理师】高分论文:论信息系统项目的风险管理(资金管控系统)
  • js -音频变音(听不出说话的人是谁)
  • mmsegmentation中img_scale的作用
  • python对mongodb的增删查改
  • STM32配合可编程加密芯片SMEC88ST的防抄板加密方案设计
  • 如何使用 `uiautomator2` 控制 Android 设备并模拟应用操作_VIVO手机
  • 局网设置mongodb服务的方法。
  • Couchbase、ClickHouse 和 Apache Doris在架构、功能、应用场景等方面的详细对比
  • 人工智能平台 PAI
  • 数据库运维学习选择
  • 深入理解计算机中的补码、反码、原码
  • Nginx根据不同ip段配置不同的访问首页
  • 逻辑回归(Logistic Regression) —— 机器学习中的经典分类算法
  • 【Nginx Docker】Office Word Web addin 部署nginx docker
  • 2024转转技术年货发布啦
  • 中建海龙:科技助力福城南产业片区绿色建筑发展
  • HarmonyOS鸿蒙开发 应用开发常见问题总结(持续更新...)
  • Python 链接 Pcomm
  • [CTF/网络安全] 攻防世界 simple_js 解题详析
  • python 插入排序(Insertion Sort)
  • MyBatis一级缓存与二级缓存详解
  • Spring Boot项目中分布式锁实现方案:Redisson
  • Java(四十四)file
  • JavaScript Math(算数) 对象的用法详解