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

kafka零拷贝技术的底层实现

什么是 Sendfile?

sendfile 是一种操作系统提供的系统调用(system call),用于在两个文件描述符(file descriptor)之间高效传输数据。它最初由 Linux 内核引入(从 2.1 版本开始),旨在优化文件数据从磁盘到网络的传输过程。sendfile 的核心优势是零拷贝(zero-copy),即避免用户空间和内核空间之间的多次数据拷贝,从而提升性能。

系统调用定义

在 Linux 中,sendfile 的函数签名如下(C 语言):

ssize_t sendfile(int out_fd, int in_fd, off_t *offset, size_t count);
  • out_fd:目标文件描述符,通常是网络套接字(socket)。
  • in_fd:源文件描述符,通常是磁盘文件。
  • offset:源文件的偏移量(可以为空,表示从当前位置开始)。
  • count:要传输的字节数。
  • 返回值:实际传输的字节数,或错误码。

Sendfile 的工作原理

传统的数据传输(不使用 sendfile)涉及以下步骤:

  1. 应用程序调用 read(),将文件数据从磁盘读取到内核缓冲区。
  2. 数据从内核缓冲区拷贝到用户空间的应用程序缓冲区。
  3. 应用程序调用 write(),将数据从用户空间缓冲区拷贝回内核的 socket 缓冲区。
  4. 内核通过网络栈将 socket 缓冲区的数据发送出去。

这个过程有 4 次上下文切换(用户态 ↔ 内核态)和 2 次数据拷贝(内核 → 用户 → 内核)。

使用 Sendfile 的优化

sendfile 将上述过程简化为:

  1. 内核直接从磁盘文件读取数据到内核缓冲区(页面缓存)。
  2. 内核将数据从页面缓存直接传输到 socket 缓冲区(通过 DMA,Direct Memory Access)。
  3. 内核通过网络栈发送数据。

优化结果:

  • 零拷贝:数据无需经过用户空间,完全在内核态完成。
  • 减少上下文切换:只需 2 次切换(调用 sendfile 和返回)。

Kafka 如何使用 Sendfile

Kafka 的高性能设计大量依赖顺序 I/O 和零拷贝技术,其中 sendfile 是关键组件之一。Kafka 在以下场景中使用 sendfile:

1. 日志文件传输
  • Kafka 的 Broker 将存储在磁盘上的日志文件(.log 文件)发送给消费者或 Follower 时,使用 sendfile。
  • 数据从日志文件直接传输到网络 socket,避免了传统拷贝的开销。
2. Java 中的实现
  • Kafka 使用 Java NIO(New I/O)中的 FileChannel.transferTo() 方法,该方法底层调用了操作系统的 sendfile(在支持的系统上)。
  • 示例代码(简化的 Kafka 数据传输逻辑):
    import java.io.File;
    import java.nio.channels.FileChannel;
    import java.nio.channels.SocketChannel;public class SendfileExample {public static void main(String[] args) throws Exception {File file = new File("data.log");FileChannel fileChannel = FileChannel.open(file.toPath());SocketChannel socketChannel = SocketChannel.open();// 使用 transferTo 实现零拷贝传输long position = 0;long count = fileChannel.size();fileChannel.transferTo(position, count, socketChannel);fileChannel.close();socketChannel.close();}
    }
    • transferTo() 在 Linux 上会映射到 sendfile,实现从文件到 socket 的高效传输。
3. Kafka 的优化点
  • 顺序读取:Kafka 的日志文件是顺序写入的,读取时也是顺序的,与 sendfile 的顺序传输特性完美匹配。
  • 批量传输:Kafka 将多条消息批量发送,sendfile 可以一次性传输大块数据,进一步减少系统调用开销。

Sendfile 的优势

Kafka 利用 sendfile 获得以下好处:

  1. 高吞吐量:减少数据拷贝和上下文切换,提升了数据传输效率。
  2. 低 CPU 使用率:DMA 处理数据移动,释放 CPU 资源。
  3. 低延迟:直接传输减少了中间环节的时间。

在基准测试中,Kafka 单节点可以达到每秒百万级消息的吞吐量,sendfile 是这一性能的重要支撑。


Sendfile 的局限性

尽管 sendfile 非常高效,但也有局限性:

  1. 仅限文件到 socket:sendfile 只能将数据从文件传输到网络,无法处理内存到网络的场景。
  2. 操作系统依赖:需要底层操作系统支持(Linux 支持,Windows 通过其他机制模拟)。
  3. 无数据处理:sendfile 不支持在传输过程中修改数据,适合 Kafka 这种直接转发日志的场景。

对于需要处理数据的场景(例如加密或压缩),Kafka 会结合其他技术(如用户空间缓冲)。


总结

  • sendfile 是什么:一种零拷贝的系统调用,用于高效传输文件数据到网络。
  • Kafka 如何使用:通过 FileChannel.transferTo() 调用 sendfile,将日志文件直接发送给消费者或 Follower。
  • 作用:提升吞吐量、降低 CPU 负载,是 Kafka 高性能的关键技术之一。

如果你想深入探讨 sendfile 在 Kafka 中的具体实现细节(例如源码分析),或者有其他疑问,请告诉我!

相关文章:

kafka零拷贝技术的底层实现

什么是 Sendfile? sendfile 是一种操作系统提供的系统调用(system call),用于在两个文件描述符(file descriptor)之间高效传输数据。它最初由 Linux 内核引入(从 2.1 版本开始)&…...

MFC中CMap类的用法和原理

1、CMap 的原理 CMap 是一个基于哈希表的映射类,它将唯一键映射到对应的值。其内部实现依赖于哈希算法,通过哈希函数将键转换为哈希值,然后将哈希值映射到哈希表中的某个位置。如果多个键的哈希值相同(即哈希冲突)&am…...

elementplus的el-tabs路由式

在使用 Element Plus 的 el-tabs 组件,实现路由式的切换(即点击标签页来切换不同的路由页面)。下面是一个基于 Vue 3 和 Element Plus 实现路由式 el-tabs 的基本步骤和示例。 步骤 1: 安装必要的库 在vue3项目安装 Vue Router 和 Element …...

数据结构初阶:单链表

序言: 本篇博客主要介绍单链表的基本概念,包括如何定义和初始化单链表,以及如何进行数据的插入,删除和销毁等操作。 1.单链表 1.1 概念与结构 概念:链表是一种非顺序的存储结构,数据元素的逻辑顺序是通过…...

北斗导航 | 改进伪距残差矢量的接收机自主完好性监测算法原理,公式,应用,RAIM算法研究综述,matlab代码

改进伪距残差矢量的接收机自主完好性监测算法研究 摘要 接收机自主完好性监测(RAIM)是保障全球卫星导航系统(GNSS)可靠性的核心技术。本文针对传统伪距残差矢量法在微小故障检测和多故障隔离中的不足,提出一种融合加权奇偶空间与动态阈值调整的改进算法。通过理论推导验证…...

RabbitMQ高级特性--TTL和死信队列

目录 1.TTL 1.1设置消息的TTL 1.1.1配置交换机&队列 1.1.2发送消息 1.1.3运行程序观察结果 1.2设置队列的TTL 1.2.1配置队列和交换机的绑定关系 1.2.2发送消息 1.2.3运行程序观察结果 1.3两者区别 2.死信队列 2.1 声名队列和交换机 2.2正常队列绑定死信交换机 …...

Java后端开发: 如何安装搭建Java开发环境《安装JDK》和 检测JDK版本

文章目录 一、JDK的安装1、 打开 Oracle 官方网址2、点击产品 二、检测JDK是否安装成功以及JDK版本的查看1. 打开命令行窗口检测是否安装成功查看 JDK 版本 一、JDK的安装 1、 打开 Oracle 官方网址 Oracle官网地址:https://www.oracle.com/cn/ 2、点击产品 打开下载的JDK文件…...

LabVIEW液压控制系统开发要点

液压控制系统开发需兼顾高实时性、强抗干扰性和安全性,尤其在重工业场景中,毫秒级响应延迟或数据异常都可能导致设备损坏。本文以某钢厂液压升降平台项目为例,从硬件选型、控制算法、安全机制三方面,详解LabVIEW开发中的关键问题与…...

鸿蒙Flutter实战:18-组合而非替换,现有插件快速鸿蒙化

引言 在对插件鸿蒙化时,除了往期文章现有Flutter项目支持鸿蒙II中讲到的使用 dependency_overrides 来配置鸿蒙适配库的两种方式以外,如果三方插件本身使用了联合插件的形式,也可以通过下面这种方式来添加鸿蒙平台的实现: depen…...

Qt之Service开发

一、概述 基于Qt的用于开发系统服务(守护进程)和后台服务,有以下几个优秀的开源 QtService 框架和库。 1. QtService (官方解决方案) GitHub: https://github.com/qtproject/qt-solutions/tree/master/qtservice 特点: 官方提供的服务框架 支持 Windows 服务和 Linux 守护…...

MFC添加免费版大漠3.1233

先创建一个MFC工程, 添加dm.dll 方法一:通过类向导-添加类-类型库中的MFC类-文件,选择dm.dll,如果没有"添加类型库中的MFC类"选项就用方法二添加 方法二:添加-新建项-MFC-Active或TypeLib-实现接口位置选…...

vue 图片放大到全局

背景: 在vue项目中,el-image组件图片组件用于展示图片,组件自带的属性preview-teleported,设置为true可以控制图片放大到全局 实现效果: 核心代码: //图片地址:BASEUrl /file/ item.file //这…...

人工智能入门(1)

人工智能导引 文章目录 人工智能导引artifiicial intelligence由图灵测试出发的六个领域贝叶斯方法分析成为大多数AI系统中不确定推理的现代方法基础 研究方法 机器学习计算机利用已经有的数据样本,得出某种规律模型,并利用模型预测未来的一种方法 回归算…...

Python爬虫:Feapder 的详细使用和案例

更多内容请见: 爬虫和逆向教程-专栏介绍和目录 文章目录 1. Feapder 概述1.1 Feapder介绍1.2 Feapder 核心特点1.3 Feapder 主要组件1.4 Feapder的安装2. 基础爬虫编写2.1 创建爬虫2.2 运行爬虫3. 数据采集案例3.1 新闻网站采集3.2 电商商品采集3.3 使用 Spider 类创建更强大爬…...

mybatis里in关键字拼接id问题

我们一般会把ids集合用StrUtil.join(‘,’)转成"1,2,3"这种形式 然后放入in中 我们会这么写: select id, nick_name, icon from tb_user where id in (#{ids}) order by FIELD(id, #{ids})结果发现sql执行是这样的: select id, nick_name, icon from tb_user where…...

在rockylinux9.4安装mongodb报错:缺少:libcrypto.so.10文件库

问题点: rockylinux9.4系统环境报错: ./mongod: error while loading shared libraries: libcrypto.so.10: cannot open shared object file: No such file or directory 解决方法: Ps:解压之后,检查mongodb的依赖环境…...

Spring Boot集成阿里云OSS:对象存储实战指南

Spring Boot集成阿里云OSS:对象存储实战指南 1. OSS是什么?为什么选择阿里云OSS? 对象存储(OSS) 是一种用于存储非结构化数据(如图片、视频、日志文件)的云服务,核心功能包括&#…...

【力扣hot100题】(019)旋转图像

比较考验脑子转不转得过来,最好先在纸上画一下图整理思路,不要和我一样上来就无脑套循环。 理解了思路还是好做的,每个小循环转一圈,大循环代表转的第几圈。小循环循环n-2i-1次,大循环循环(n1)…...

06_约束

文章目录 一、是什么二、实体完整性约束2.1、主键约束2.2、主键自增长2.3、唯一约束 三、域完整性约束3.1、非空约束3.2、默认值 四、引用完整性约束 一、是什么 用于限制加入表的数据的类型和规范,约束是添加在列上的,用来约束列的。 分类: …...

Anolis OS 8.4修复CVE-1999-0554漏洞记录

1. 使用TCP Wrappers配置白名单 通过修改/etc/hosts.allow和/etc/hosts.deny文件,仅允许特定IP访问NFS的mountd服务(需确保系统支持TCP Wrappers): 编辑/etc/hosts.allow,添加允许的客户端IP(如192.168.1…...

Seata AT模式的一些常见问题及其源码解析

Seata 是一款开源的分布式事务解决方案,致力于提供高性能和简单易用的分布式事务服务。Seata 将为用户提供了 AT、TCC、SAGA 和 XA 事务模式,为用户打造一站式的分布式解决方案。 Seata AT 基于两阶段提交协议的演变: 一阶段:业…...

华为GaussDB数据库的手动备份与还原操作介绍

数据库的备份以A机上的操作为例。 1、使用linux的root用户登录到GaussDB服务器。 2、用以下命令切换到 GaussDB 管理员用户,其中,omm 为当前数据库的linux账号。 su - omm 3、执行gs_dump命令进行数据库备份: 这里使用gs_dump命令进行备…...

2025年3月29日(matlab -ss -lti)

线性时不变系统(LTI系统)的定义与核心特性 线性时不变系统(Linear Time-Invariant System)是信号与系统分析中的基础模型,其核心特性包括线性和时不变性。以下从定义、验证方法和应用场景展开说明: 1. 线性…...

网络原理-TCP/IP

网络原理学习笔记:TCP/IP 核心概念 本文是我在学习网络原理时整理的笔记,主要涵盖传输层、网络层和数据链路层的核心协议和概念,特别是 TCP, UDP, IP, 和以太网。 一、传输层 (Transport Layer) 传输层负责提供端到端(进程到进…...

服务器磁盘卷组缓存cache设置介绍

工具1: storcli a. 确认软件包是否安装 [rootlocalhost ~]#rpm -qa | grep storcli storcli-1.21.06-1.noarch 备注:若检索结果为空,需要安装对应的软件安装包。安装命令如下: #rpm -ivh storcli-xx-xx-1.noarch.rpm b. 查看逻辑…...

Unity顶点优化:UV Splits与Smoothing Splits消除技巧

一、顶点分裂问题概述 1. 什么是顶点分裂 顶点分裂(Vertex Splits)是3D渲染中常见的性能问题,当模型需要为同一顶点位置存储不同属性值时,会创建多个顶点副本。主要分为两类: UV Splits:由UV不连续引起 Smoothing Splits&#…...

第五十三章 Spring之假如让你来写Boot——环境篇

Spring源码阅读目录 第一部分——IOC篇 第一章 Spring之最熟悉的陌生人——IOC 第二章 Spring之假如让你来写IOC容器——加载资源篇 第三章 Spring之假如让你来写IOC容器——解析配置文件篇 第四章 Spring之假如让你来写IOC容器——XML配置文件篇 第五章 Spring之假如让你来写…...

Router [Continuation Settings]

楼上网络CMCC-Wmew,楼下接收不到,可能因为喜好弱,再弄一台路由器中转一下 Router [Continuation Settings] 路由器中续设置 到这里这台K3的路由器设置完成了,作为转发,中续,她还需要设置上游路由器&#…...

Zookeeper中的Zxid是如何设计的

想获取更多高质量的Java技术文章?欢迎访问Java技术小馆官网,持续更新优质内容,助力技术成长 Java技术小馆官网https://www.yuque.com/jtostring Zookeeper中的Zxid是如何设计的 如果你们之前学习过 ZooKeeper,你们可能已经了解…...

蓝桥云客 岛屿个数

0岛屿个数 - 蓝桥云课 问题描述 小蓝得到了一副大小为 MN 的格子地图,可以将其视作一个只包含字符 0(代表海水)和 1(代表陆地)的二维数组,地图之外可以视作全部是海水,每个岛屿由在上/下/左/右…...