放荡的人生|面试题详解:Kafka为什么能那么快的6个原因( 三 )

  • 磁盘文件通过网络发送(Broker 到 Consumer)
  • 4.1 网络数据持久化到磁盘 (Producer 到 Broker)传统模式下 , 数据从网络传输到文件需要 4 次数据拷贝、4 次上下文切换和两次系统调用 。
    • data = http://kandian.youth.cn/index/socket.read()// 读取网络数据
    • File file = new File()
    • file.write(data)// 持久化到磁盘
    • file.flush()
    这一过程实际上发生了四次数据拷贝:
    1. 首先通过 DMA copy 将网络数据拷贝到内核态 Socket Buffer
    2. 然后应用程序将内核态 Buffer 数据读入用户态(CPU copy)
    3. 接着用户程序将用户态 Buffer 再拷贝到内核态(CPU copy)
    4. 最后通过 DMA copy 将数据拷贝到磁盘文件
    “DMA(Direct Memory Access):直接存储器访问 。 DMA 是一种无需 CPU 的参与 , 让外设和系统内存之间进行双向数据传输的硬件机制 。 使用 DMA 可以使系统 CPU 从实际的 I/O 数据传输过程中摆脱出来 , 从而大大提高系统的吞吐率 。
    同时 , 还伴随着四次上下文切换 , 如下图所示
    放荡的人生|面试题详解:Kafka为什么能那么快的6个原因数据落盘通常都是非实时的 , kafka 生产者数据持久化也是如此 。 Kafka 的数据并不是实时的写入硬盘 , 它充分利用了现代操作系统分页存储来利用内存提高 I/O 效率 , 就是上一节提到的 Page Cache 。
    对于 kafka 来说 , Producer 生产的数据存到 broker , 这个过程读取到 socket buffer 的网络数据 , 其实可以直接在内核空间完成落盘 。 并没有必要将 socket buffer 的网络数据 , 读取到应用进程缓冲区;在这里应用进程缓冲区其实就是 broker , broker 收到生产者的数据 , 就是为了持久化 。
    在此特殊场景下:接收来自 socket buffer 的网络数据 , 应用进程不需要中间处理、直接进行持久化时 。 可以使用 mmap 内存文件映射 。
    “Memory Mapped Files:简称 mmap , 也有叫 MMFile 的 , 使用 mmap 的目的是将内核中读缓冲区(read buffer)的地址与用户空间的缓冲区(user buffer)进行映射 。 从而实现内核缓冲区与应用程序内存的共享 , 省去了将数据从内核读缓冲区(read buffer)拷贝到用户缓冲区(user buffer)的过程 。 它的工作原理是直接利用操作系统的 Page 来实现文件到物理内存的直接映射 。 完成映射之后你对物理内存的操作会被同步到硬盘上 。
    使用这种方式可以获取很大的 I/O 提升 , 省去了用户空间到内核空间复制的开销 。
    mmap 也有一个很明显的缺陷——不可靠 , 写到 mmap 中的数据并没有被真正的写到硬盘 , 操作系统会在程序主动调用 flush 的时候才把数据真正的写到硬盘 。 Kafka 提供了一个参数——producer.type 来控制是不是主动flush;如果 Kafka 写入到 mmap 之后就立即 flush 然后再返回 Producer 叫同步(sync);写入 mmap 之后立即返回 Producer 不调用 flush 就叫异步(async) , 默认是 sync 。
    放荡的人生|面试题详解:Kafka为什么能那么快的6个原因“零拷贝(Zero-copy)技术指在计算机执行操作时 , CPU 不需要先将数据从一个内存区域复制到另一个内存区域 , 从而可以减少上下文切换以及 CPU 的拷贝时间 。
    它的作用是在数据报从网络设备到用户程序空间传递的过程中 , 减少数据拷贝次数 , 减少系统调用 , 实现 CPU 的零参与 , 彻底消除 CPU 在这方面的负载 。
    目前零拷贝技术主要有三种类型[3]: