消息队列选型:Kafka 如何实现高性能?

2023-12-19

在分布式消息模块中,我将对消息队列中应用最广泛的 Kafka 和 RocketMQ 进行梳理,以便于你在应用中可以更好地进行消息队列选型。另外,这两款消息队列也是面试的高频考点。

所以,本文我们就一起来看一下,Kafka 是如何实现高性能的。

Kafka 的高性能

不知道你有没有了解过自己电脑的配置?

我们一般会认为高性能是和高配置联系在一起的,比如大内存比小内存快,8 核的机器比 4 核的机器快。我身边也有一些朋友是攒机爱好者,对各种硬件配置如数家珍。

对于服务器来说,家用电脑的性能与配置的关系也同样适用——价格更昂贵的服务器会有更好的性能——这并不是一件需要大张旗鼓去讲述的事情。但 Kafka 所实现的高性能不需要太高配置的机器,它使用普通服务器就能实现 TB 级别的传输性能。这一点也是 Kafka 对外宣传的一个特性,也正是因为这一点,Kafka 被广泛运用于大数据处理、流式计算、各类日志监控等需要处理海量数据的场景。

Kafka 实现高性能的手段,是面试中经常被问到的问题。下面我从 Kafka 的磁盘读写、批量优化、零拷贝等方面,对 Kafka 的高性能特性进行分析。

分析 Kafka 的高性能会涉及操作系统的一些知识,比如文件系统、PageCache等,作为大学计算机专业的必修课,这些概念就不展开了。如果你觉得这方面比较生疏,可以回顾下操作系统课程的相关知识,找一些经典教材来学习。

磁盘顺序读写

Kafka 消息是存储在磁盘上的,大家都知道,普通的机械磁盘读取是比较慢的,那 Kafka 文件在磁盘上,如何实现高性能的读写呢?

Kafka 对磁盘的应用,得益于消息队列的存储特性。与普通的关系型数据库、各类 NoSQL 数据库等不同,消息队列对外提供的主要方法是 生产和消费 ,不涉及数据的 CRUD。所以在写入磁盘时,可以使用顺序追加的方式来避免低效的磁盘寻址。

我们知道,数据存储在硬盘上,而硬盘有机械硬盘和固态硬盘之分。机械硬盘成本低、容量大,但每次读写都会寻址,再写入数据(在机械硬盘上,寻址是一个物理动作,耗时最大);SSD 固态硬盘性能很高,有着非常低的寻道时间和存取时间,但成本也特别高。

为了提高在机械硬盘上读写的速度,Kafka 使用了顺序读写。在一个分区内,Kafka 采用 append 的方式进行顺序写入,这样即使是普通的机械磁盘,也可以有很高的性能。

除了顺序读写,在提到磁盘写入的时候,还有一个问题避免不了,那就是何时进行刷盘。

在 Linux 系统中,当我们把数据写入文件系统之后,其实数据是存放在操作系统的 page cache 里面,并没有刷到磁盘上,如果服务器宕机,数据就丢失了。

写到磁盘的过程叫作 Flush。刷盘一般有两种方式,一种是依靠操作系统进行管理,定时刷盘,另一种则是同步刷盘,比如调用 fsync 等系统函数。

同步刷盘保证了数据的可靠性,但是会降低整体性能。Kafka 可以配置异步刷盘,不开启同步刷盘,异步刷盘不需要等写入磁盘后返回消息投递的 ACK,所以它提高了消息发送的吞吐量,降低了请求的延时,这也是 Kafka 磁盘高性能的一个原因。

批量操作优化

批量是一个常见的优化思路,比如大家熟悉的 Redis,就实现了 pipeline 管道批量操作。Kafka 在很多地方也应用了批量操作进行性能优化。

Kafka 的批量包括批量写入、批量发布等。它在消息投递时会将消息缓存起来,然后批量发送;同样,消费端在消费消息时,也不是一条一条处理的,而是批量进行拉取,提高了消息的处理速度。

除了批量以外,Kafka 的数据传输还可以配置压缩协议,比如 Gzip 和 Snappy 压缩协议。虽然在进行数据压缩时会消耗少量的 CPU 资源,但可以减少网络传输的数据大小、优化网络 IO、提升传输速率。

Sendfile 零拷贝

零拷贝是什么?它是操作系统文件读写的一种技术。

零拷贝不是不需要拷贝,而是减少不必要的拷贝次数,这里会涉及 Linux 用户态和内核态的区别。

用户进程是运行在用户空间的,不能直接操作内核缓冲区的数据。所以在用户进程进行系统调用的时候,会由用户态切换到内核态,待内核处理完之后再返回用户态。

传统的 IO 流程,需要先把数据拷贝到内核缓冲区,再从内核缓冲拷贝到用户空间,应用程序处理完成以后,再拷贝回内核缓冲区。这个过程中发生了多次数据拷贝。

为了减少不必要的拷贝,Kafka 依赖 Linux 内核提供的 Sendfile 系统调用。 在 Sendfile 方法中,数据在内核缓冲区完成输入和输出,不需要拷贝到用户空间处理,这也就避免了重复的数据拷贝。在具体的操作中,Kafka 把所有的消息都存放在单独的文件里,在消息投递时直接通过 Sendfile 方法发送文件,减少了上下文切换,因此大大提高了性能。

MMAP 技术

Kafka 是使用 Scala 语言开发的。Scala 运行在 Java 虚拟机上,也就是说 Kafka 节点运行需要 JVM 的支持,但是 Kafka 并不直接依赖 JVM 堆内存。如果 Kafka 所有的数据操作都在堆内存中进行,则会对堆内存造成非常大的压力,影响垃圾回收处理,增加 JVM 的停顿时间和整体延迟。

因此,除了 Sendfile 之外,还有一种零拷贝的实现技术,即 Memory Mapped Files。

Kafka 使用 Memory Mapped Files 完成内存映射,Memory Mapped Files 对文件的操作不是 write/read,而是直接对内存地址的操作。如果是调用文件的 read 操作,则把数据先读取到内核空间中,然后再复制到用户空间。 但 MMAP 可以将文件直接映射到用户态的内存空间,省去了用户空间到内核空间复制的开销,所以说 MMAP 也是一种零拷贝技术。

那 MMAP 和上面的 Sendfile 有什么区别呢?

MMAP 和 Sendfile 并没有本质上的区别,它们都是零拷贝的实现。零拷贝是一种技术思想,除了我们说到的这两种,还有DMA,以及缓冲区共享等方式,感兴趣的同学可以去扩展了解一下。

总结

本文讲解了 Kafka 如何实现高性能,介绍了顺序读写、批量优化、零拷贝等技术,对于大部分业务开发的同学,这部分知识了解即可。

Kafka 的高性能实现原理,在很多地方都有应用,比如 Netty 中也有零拷贝技术。Linux 中,一切皆文件,Netty 关注的是网络 IO 的传输,Kafka 等存储关注的是文件 IO 的传输,但在操作系统中都是 IO 操作,在优化手段上非常类似。

另外,上面提到的 Sendfile 可以大幅提升文件传输性能,在 Apache、Nginx 等 Web 服务器当中,都有相关的应用。感兴趣的同学可以了解下 Netty 等网络组件的性能优化方式,欢迎留言进行分享。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

消息队列选型:Kafka 如何实现高性能? 的相关文章

随机推荐

  • ros2+xacro文件示例代码备份

    重要提示 在xacro文件虽然是xml文件 但是如果在xacro文件中随意插入自定义标签 虽然check urdf不会报错 但是最后rviz2解析的时候会出现错误 例如 如果在上述xml文件中加入以下代码将出现显示异常
  • 安装登录minio后,页面一直转圈

    报错 WARNING MINIO ACCESS KEY and MINIO SECRET KEY are deprecated Please use MINIO ROOT USER and MINIO ROOT PASSWORD 处理方案
  • Starting the Docker Engine...一直转圈

    出现的问题 原因排查 看了网上的很多篇文章 每个原因都排查了 没有发现问题 遇到这样的情况应先看自己是否安装成功 打开运行 在空框中输入 powershell 并点击确定 docker version 显示版本证明安装成功 Hyper V
  • 基于振弦采集仪的工程监测技术探索

    基于振弦采集仪的工程监测技术探索 随着工程建设的日益发展 对工程监测的需求也越来越迫切 工程监测是保障工程质量和安全的重要手段 而基于振弦采集仪的工程监测技术 由于其高精度 高灵敏度和实时性等特点 正逐渐成为工程监测领域的重要技术 振弦采集
  • ubuntu推送本地仓库到coding

    本教程提供在ubuntu系统下推送本地仓库到coding的指令 用于查阅 一 主要步骤有 0 初始化仓库 git init 1 添加远程仓库 git remote add origin https coding git 修改自己仓库链接 命
  • 题解 | #输出某一年的各个月份的天数#

    三方寄过去了 告诉我停止24届招聘 全部毁约 牛的 he芯 毁约应届生 34316 广西北部湾银行2022年校园招聘 广西北部湾银行股份有限公司2022届校园招聘 看终端大把大把15级的 这个14级是不是终端bg的白菜了 程序员面试六战六捷
  • 市域治理现代化建设方案(智慧网格解决方案):PPT全文33页,附下载

    关键词 市域治理现代化 智慧网格解决方案 市域治理主要内容 市域社会治理重点内容 市域社会治理现代化 一 市域治理现代化背景 1 城市化进程加速 随着城市化进程的快速推进 城市人口不断增加 城市规模不断扩大 城市治理面临着更加复杂的挑战 2
  • CNP日志采集组件使用说明

    移动云CNP上线了日志采集组件 整体功能类似ELK 可以实现集群容器日志的数据采集 汇聚 统一检索等功能 使用也很简单 首先安装组件 然后配置采集规则 目前支持标准输出和日志文件两种采集方案 标准输出很好理解 只需要你把日式输出到控制台 这
  • json转换工具属性排序

    json 对象属性的输出顺序测试 fastJson 有序 jackson gson无序 需代码中人工按约定来编码 接口数据签名规则 fastJson会根据对象的字段的首字母来排序 而jackson gson是根据对象的类中定义的属性的代码中
  • 工业5G路由器助力AGV工厂建设,确保自动流水线高效运转

    随着制造业自动化 智能化转型升级的需求 山东省济南市一家汽车零部件生产企业计划建设全自动生产流水线 并使用AGV替代部分人工运输 以降本提效 但是对无线通信要求极高的AGV系统在复杂的工厂建筑内很难获得稳定的信号覆盖 AGV之间 与控制中心
  • Redis 的键管理

    一 Redis 数据库管理 Redis 是一个键值对 key value pair 的数据库服务器 其数据保存在 src server h redisDb 中 网上很多帖子说在 redis h 文件中 但是 redis 6 x版本目录中都没
  • HONEYWELL 05701-A-0361 离散输入/输出模块

    HONEYWELL 05701 A 0361 离散输入 输出模块 HONEYWELL 05701 A 0361 离散输入 输出模块产品详情 HONEYWELL 05701 A 0361 离散输入 输出模块通常用于工业自动化系统中 用于处理数
  • BENTLY 125680-01 位移检测模块

    BENTLY 125680 01 位移检测模块 BENTLY 125680 01 位移检测模块产品详情 Bently 125680 01 是一款位移检测模块 通常用于监测和测量工业设备的位移或振动 Bently Nevada是一家以提供振动
  • 【老生谈算法】matlab实现基于粒子群算法的PID控制器优化设计——粒子群算法

    Matlab实现基于粒子群算法的PID控制器优化设计 1 文档下载 本算法已经整理成文档如下 有需要的朋友可以点击进行下载 说明 文档 点击下载 本算法文档 老生谈算法 matlab实现基于粒子群算法的PID控制器优化设计 doc 更多ma
  • android 将服务设置为前台服务

    NotificationChannel channel new NotificationChannel id com xxx xx XxxService NotificationManager IMPORTANCE NONE channel
  • 【LeetCode刷题笔记】位运算

    231 2 的幂 解题思路 1 除法 不断循环判断 如果能被 2 整除 就不断除以 2 直到不能被 2 整除为止 最后结果如果是 1
  • HONEYWELL 05701-A-0511 框架模块

    HONEYWELL 05701 A 0511 框架模块 HONEYWELL 05701 A 0511 框架模块 产品详情 框架模块通常是一种用于构建更大型 更复杂系统的组件 在自动化和控制系统中 框架模块可能用于提供某些基础结构或功能 以支
  • 德思特EMC RICI测试方案助您对抗电磁设备干扰!

    来源 德思特测试测量 德思特方案丨德思特EMC RICI测试方案助您对抗电磁设备干扰 原文链接 https mp weixin qq com s D8wdQr reaFG yppT8nzkw 欢迎关注虹科 为您提供最新资讯 方案背景 电磁或
  • 企业电子招标采购系统源码Spring Cloud + Spring Boot + 前后端分离 + 二次开发

    项目说明 随着公司的快速发展 企业人员和经营规模不断壮大 公司对内部招采管理的提升提出了更高的要求 在企业里建立一个公平 公开 公正的采购环境 最大限度控制采购成本至关重要 符合国家电子招投标法律法规及相关规范 以及审计监督要求 通过电子化
  • 消息队列选型:Kafka 如何实现高性能?

    在分布式消息模块中 我将对消息队列中应用最广泛的 Kafka 和 RocketMQ 进行梳理 以便于你在应用中可以更好地进行消息队列选型 另外 这两款消息队列也是面试的高频考点 所以 本文我们就一起来看一下 Kafka 是如何实现高性能的