零拷贝技术、常见实现方案、Kafka中的零拷贝技术的使用、Kafka为什么这么快

目录

1. 普通拷贝

2. 数据拷贝基础过程

2.1 仅CPU方式

2.2 CPU&DMA方式

3.普通模式数据交互

4. 零拷贝技术

4.1 出现原因

4.2 解决思路

4.2.1 mmap方式

4.2.2 sendfile方式

4.2.3 sendfile+DMA收集

4.2.4 splice方式

5. Kafka中使用到的零拷贝技术

参考链接

本文参考这篇文章书写:【linux】图文并茂|彻底搞懂零拷贝(Zero-Copy)技术 - 知乎 (zhihu.com)


1. 普通拷贝

        考虑这样一种常用的情形:你需要将静态内容(类似图片、文件)展示给用户。这个情形就意味着需要先将静态内容从磁盘中复制出来放到一个内存 buf 中,然后将这个 buf 通过套接字(Socket)传输给用户,进而用户获得静态内容。可以将其抽象为如下伪代码:

read(file, tmp_buf, len);
write(socket, tmp_buf, len);

        首先通过read() 将静态内容读取到用户缓冲区,然后调用write()将用户缓冲区的内容写入到Socket。

在这个过程中,普通文件(A)需要经过4次复制过程:

  1. 调用read(),将文件A的内容复制到内核模式的Read Buffer中。
  2. CPU控制将内核模式数据复制到用户模式下。
  3. 调用write(),将用户模式下的内容复制到内核模式下的Socket Buffer中。
  4. 将内核模式下的Socket Buffer的数据复制到网卡设备中传输。

        Linux系统中一切皆文件,仔细想一下Linux系统的很多活动无外乎读操作写操作,零拷贝就是为了提高读写性能而出现的。

2. 数据拷贝基础过程

        在Linux系统内部缓存和内存容量都是有限的,更多的数据都是存储在磁盘中。对于Web服务器来说,经常需要从磁盘中读取数据到内存,然后再通过网卡传输给用户:

上述数据流转只是大框,接下来看看几种模式。

2.1 仅CPU方式

  • 当应用程序需要读取磁盘数据时,调用read()从用户态陷入内核态,read()这个系统调用最终由CPU来完成;
  • CPU向磁盘发起I/O请求,磁盘收到之后开始准备数据;
  • 磁盘将数据放到磁盘缓冲区之后,向CPU发起I/O中断,报告CPU数据已经Ready了;
  • CPU收到磁盘控制器的I/O中断之后,开始拷贝数据,完成之后read()返回,再从内核态切换到用户态;

2.2 CPU&DMA方式

        CPU的时间宝贵,让它做杂活就是浪费资源。

        直接内存访问(Direct Memory Access),是一种硬件设备绕开CPU独立直接访问内存的机制。所以DMA在一定程度上解放了CPU,把之前CPU的杂活让硬件直接自己做了,提高了CPU效率。

        目前支持DMA的硬件包括:网卡、声卡、显卡、磁盘控制器等。

有了DMA的参与之后的流程发生了一些变化:

最主要的变化是,CPU不再和磁盘直接交互,而是DMA和磁盘交互并且将数据从磁盘缓冲区拷贝到内核缓冲区,之后的过程类似。

“【 敲黑板】无论从仅CPU方式和DMA&CPU方式,都存在多次冗余数据拷贝和内核态&用户态的切换。

我们继续思考Web服务器读取本地磁盘文件数据再通过网络传输给用户的详细过程。

3.普通模式数据交互

一次完成的数据交互包括几个部分:系统调用syscall、CPU、DMA、网卡、磁盘等。

系统调用syscall是应用程序和内核交互的桥梁,每次进行调用/返回就会产生两次切换:

  • 调用syscall 从用户态切换到内核态
  • syscall返回 从内核态切换到用户态

来看下完整的数据拷贝过程简图:

读数据过程:

  • 应用程序要读取磁盘数据,调用read()函数从而实现用户态切换内核态,这是第1次状态切换;
  • DMA控制器将数据从磁盘拷贝到内核缓冲区,这是第1次DMA拷贝;
  • CPU将数据从内核缓冲区复制到用户缓冲区,这是第1次CPU拷贝;
  • CPU完成拷贝之后,read()函数返回实现用户态切换用户态,这是第2次状态切换;

写数据过程:

  • 应用程序要向网卡写数据,调用write()函数实现用户态切换内核态,这是第1次切换;
  • CPU将用户缓冲区数据拷贝到内核缓冲区,这是第1次CPU拷贝;
  • DMA控制器将数据从内核缓冲区复制到socket缓冲区,这是第1次DMA拷贝;
  • 完成拷贝之后,write()函数返回实现内核态切换用户态,这是第2次切换;

综上所述:

  • 读过程涉及2次空间切换、1次DMA拷贝、1次CPU拷贝;
  • 写过程涉及2次空间切换、1次DMA拷贝、1次CPU拷贝;

可见传统模式下,涉及多次空间切换和数据冗余拷贝,效率并不高,接下来就该零拷贝技术出场了。

4. 零拷贝技术

4.1 出现原因

我们可以看到,如果应用程序不对数据做修改,从内核缓冲区到用户缓冲区,再从用户缓冲区到内核缓冲区。两次数据拷贝都需要CPU的参与,并且涉及用户态与内核态的多次切换,加重了CPU负担。

我们需要降低冗余数据拷贝、解放CPU,这也就是零拷贝Zero-Copy技术。

4.2 解决思路

目前来看,零拷贝技术的几个实现手段包括:mmap+write、sendfile、sendfile+DMA收集、splice等。

4.2.1 mmap方式

        mmap是Linux提供的一种内存映射文件的机制,它实现了将内核缓冲区地址与用户空间缓冲区地址进行映射,从而实现内核缓冲区与用户缓冲区的共享。这样就减少了一次用户态和内核态的CPU拷贝,但是在内核空间内仍然有一次CPU拷贝。

这样就减少了一次用户态和内核态的CPU拷贝,但是在内核空间内仍然有一次CPU拷贝。

mmap对大文件传输有一定优势,但是小文件可能出现碎片,并且在多个进程同时操作文件时可能产生引发coredump的signal。

4.2.2 sendfile方式

        sendfile是一种在网络传输中实现零拷贝的方式。sendfile() 是一种特殊的系统调用,它允许在内核空间和用户空间之间直接传输数据,避免了数据在内核和用户空间之间的额外拷贝。这在高性能的网络传输中非常有效。

        mmap+write方式有一定改进,但是由系统调用引起的状态切换并没有减少。

        sendfile系统调用是在 Linux 内核2.1版本中被引入,它建立了两个文件之间的传输通道。

        sendfile方式只使用一个函数就可以完成之前的read+write 和 mmap+write的功能,这样就少了2次状态切换,由于数据不经过用户缓冲区,因此该数据无法被修改。

从图中可以看到,应用程序只需要调用sendfile函数即可完成,只有2次状态切换、1次CPU拷贝、2次DMA拷贝。

但是sendfile在内核缓冲区和socket缓冲区仍然存在一次CPU拷贝,或许这个还可以优化。

4.2.3 sendfile+DMA收集

Linux 2.4 内核对 sendfile 系统调用进行优化,但是需要硬件DMA控制器的配合。

升级后的sendfile将内核空间缓冲区中对应的数据描述信息(文件描述符、地址偏移量等信息)记录到socket缓冲区中。

DMA控制器根据socket缓冲区中的地址和偏移量将数据从内核缓冲区拷贝到网卡中,从而省去了内核空间中仅剩1次CPU拷贝。

这种方式有2次状态切换、0次CPU拷贝、2次DMA拷贝,但是仍然无法对数据进行修改,并且需要硬件层面DMA的支持,并且sendfile只能将文件数据拷贝到socket描述符上,有一定的局限性。

4.2.4 splice方式

splice系统调用是Linux 在 2.6 版本引入的,其不需要硬件支持,并且不再限定于socket上,实现两个普通文件之间的数据零拷贝。

splice 系统调用可以在内核缓冲区和socket缓冲区之间建立管道来传输数据,避免了两者之间的 CPU 拷贝操作。

splice也有一些局限,它的两个文件描述符参数中有一个必须是管道设备。

5. Kafka中使用到的零拷贝技术

  • Producer生产的数据持久化到broker,采用mmap文件映射,实现顺序的快速写入;
  • Customer从broker读取数据,采用sendfile,将磁盘文件读到OS内核缓冲区后,直接转到socket buffer进行网络发送。

参考链接

Kafka 中所谓的 ‘零拷贝’ 技术到底是什么?-腾讯云开发者社区-腾讯云 (tencent.com)

【linux】图文并茂|彻底搞懂零拷贝(Zero-Copy)技术 - 知乎 (zhihu.com)

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/781132.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

【学习笔记】java项目—苍穹外卖day03

文章目录 苍穹外卖-day03课程内容1. 公共字段自动填充1.1 问题分析1.2 实现思路1.3 代码开发1.3.1 步骤一1.3.2 步骤二1.3.3 步骤三 1.4 功能测试1.5 代码提交 2. 新增菜品2.1 需求分析与设计2.1.1 产品原型2.1.2 接口设计2.1.3 表设计 2.2 代码开发2.2.1 文件上传实现2.2.2 新…

uniapp 微信小程序 输入框跟随手机键盘弹起

需求&#xff1a;手机键盘弹起后&#xff0c;页面底部的输入框跟随弹起&#xff0c;且页面不被顶上去 html: <textareaclass"textinput"placeholder-class"input-place"auto-height:maxlength"2000"v-model"text"placeholder"…

微机原理-基于8086倒计时多路抢答器系统

**单片机设计介绍&#xff0c;微机原理-基于8086倒计时多路抢答器系统 文章目录 一 概要二、功能设计三、 软件设计原理图 五、 程序六、 文章目录 一 概要 微机原理-基于8086倒计时多路抢答器系统概要主要关注于利用8086微处理器设计和实现一个具有倒计时功能的多路抢答器系统…

鸿蒙OS开发实例:【消息传递】

介绍 在HarmonyOS中&#xff0c;参考官方指导&#xff0c;其实你会发现在‘指南’和‘API参考’两个文档中&#xff0c;对消息传递使用的技术不是一对一的关系&#xff0c;那么今天这篇文章带你全面了解HarmonyOS 中的消息传递 概况 参照官方指导&#xff0c;我总结了两部分…

关于Oracle VM VirtualBox无法查询IP地址的原因

1.如下&#xff0c;输入ifconfig却没有显示我框住的显示IP。 2.原因有可能&#xff1a; &#xff08;1&#xff09;主机没连上网络。 &#xff08;2&#xff09;虚拟机网络设置不正确。

生成 SSH 公钥

Windows 用户建议使用 Windows PowerShell 或者 Git Bash&#xff0c;在 命令提示符 下无 cat 和 ls 命令。 1、通过命令 ssh-keygen 生成 SSH Key&#xff1a; ssh-keygen -t ed25519 -C "Gitee SSH Key"-t key 类型 -C 注释 输出&#xff0c;如&#xff1a; 中间…

【OpenCV】 OpenCV (C++) 与 OpenCvSharp (C#) 之间数据通信

OpenCV是一个基于Apache2.0许可&#xff08;开源&#xff09;发行的跨平台计算机视觉和机器学习软件库&#xff0c;可以运行在Linux、Windows、Android和Mac OS操作系统上。 它轻量级而且高效——由一系列 C 函数和少量 C 类构成&#xff0c;同时提供了Python、Ruby、MATLAB等语…

LabVIEW转动设备故障诊断系统

LabVIEW转动设备故障诊断系统 随着工业自动化技术的不断进步&#xff0c;转动设备在电力、化工、船舶等多个行业中扮演着越来越重要的角色。然而&#xff0c;这些设备在长期运行过程中难免会出现故障&#xff0c;如果不能及时诊断和处理&#xff0c;将会导致生产效率下降&…

总结UDP协议各类知识点

前言 本篇博客博主将详细地介绍UDP有关知识点&#xff0c;坐好板凳发车啦~ 一.UDP特点 1.无连接 UDP传输的过程类似于发短信&#xff0c;知道对端的IP和端口号就直接进行传输&#xff0c;不需要建立连接&#xff1b; 2.不可靠传输 没有任何的安全机制&#xff0c;发送端发…

【AI】命令行调用大模型

&#x1f308;个人主页: 鑫宝Code &#x1f525;热门专栏: 闲话杂谈&#xff5c; 炫酷HTML | JavaScript基础 ​&#x1f4ab;个人格言: "如无必要&#xff0c;勿增实体" 文章目录 【AI】命令行调用大模型引入正文初始化项目撰写脚本全局安装 成果展示 【AI】命令…

探索高效开发大屏可视化项目模板:es-big-screen

一、引言 在数据驱动的时代&#xff0c;大屏可视化已经成为了展示数据和信息的重要手段。本文将介绍一个基于 Vue 3、Echarts、高德地图和 Pinia 开发的大屏可视化项目模板——es-big-screen&#xff0c;它提供了丰富的功能&#xff0c;包括大屏适配、图表组件&#xff08;Ech…

49 el-input 的 模型 视图 双向同步

前言 这里来看一下 el-input 这边的 数据 和 视图的双向绑定 最开始 我以为 这部分的处理应该是 vue 这边实现的, 但是跟踪调试了一下 发现这部分的处理是业务这边 自己实现的 这部分 还是有一些 值得记录的东西, 从这里 要去理解的而是 vue 这边从宏观的框架上面来说 帮我们…

前端-深入探讨网络面试题

第一关 请求-文件、数据、连接 文件类的请求&#xff1a;加载HTMl、CSS 数据&#xff1a; ajax请求&#xff08;基于HTTP&#xff0c;HTTP基于TCP&#xff09;&#xff0c;如何建立连接的&#xff08;三次握手&#xff0c;为什么不是两次或者四次&#xff09;&#xff0c;sock…

《QT实用小工具·四》屏幕拾色器

1、概述 源码放在文章末尾 该项目实现了屏幕拾色器的功能&#xff0c;可以根据鼠标指定的位置识别当前位置的颜色 项目功能包含&#xff1a; 鼠标按下实时采集鼠标处的颜色。 实时显示颜色值。 支持16进制格式和rgb格式。 实时显示预览颜色。 根据背景色自动计算合适的前景色…

AIGC重塑金融:AI大模型驱动的金融变革与实践

&#x1f308;个人主页: Aileen_0v0 &#x1f525;热门专栏: 华为鸿蒙系统学习|计算机网络|数据结构与算法 ​&#x1f4ab;个人格言:“没有罗马,那就自己创造罗马~” #mermaid-svg-tVrfBkGvUD0Qi13F {font-family:"trebuchet ms",verdana,arial,sans-serif;font-siz…

基于SpringBoot的“游戏分享网站”的设计与实现(源码+数据库+文档+PPT)

基于SpringBoot的“游戏分享网站”的设计与实现&#xff08;源码数据库文档PPT) 开发语言&#xff1a;Java 数据库&#xff1a;MySQL 技术&#xff1a;SpringBoot 工具&#xff1a;IDEA/Ecilpse、Navicat、Maven 系统展示 系统总体结构图 网站首页界面图 用户注册界面图 …

[SpringCloud] Feign Client 的创建 (二) (五)

文章目录 1.自动配置FeignAutoConfiguration2.生成 Feign Client2.1 从Feign Client子容器获取组件2.2 Feign Client子容器的创建2.3 构建Feign Client实例 1.自动配置FeignAutoConfiguration spring-cloud-starter-openfeign 包含了 spring-cloud-openfeign-core FeignAutoCo…

HarmonyOS实战开发-如何实现一个支持加减乘除混合运算的计算器。

介绍 本篇Codelab基于基础组件、容器组件&#xff0c;实现一个支持加减乘除混合运算的计算器。 说明&#xff1a; 由于数字都是双精度浮点数&#xff0c;在计算机中是二进制存储数据的&#xff0c;因此小数和非安全整数&#xff08;超过整数的安全范围[-Math.pow(2, 53)&#…

【详解】运算放大器工作原理及其在信号处理中的核心作用

什么是运算放大器 运算放大器&#xff08;简称“运放”&#xff09;是一种放大倍数非常高的电路单元。在实际电路中&#xff0c;它常常与反馈网络一起组成一定的功能模块。它是一种带有特殊耦合电路和反馈的放大器。输出信号可以是输入信号的加法、减法、微分和积分等数学运算…

vue3+ts项目 | axios 的测试 | 测试接口

在 App.vue 中&#xff0c;测试接口 // 测试接口import request from /utils/request;import { onMounted } from vue;onMounted(() > {request.get(/hosp/hospital/1/10).then((res) > {console.log("APP组件展示获取的数据",res);})}) 在request.ts中&…