2023-07-31  阅读(2)
原文作者:Ressmix 原文地址:https://www.tpvlog.com/article/279

Kafka具有 高吞吐低延迟 的特性。那么Kafka是如何实现的呢?这就涉及到消息的持久化机制了。Kafka会将消息追加到分区日志文件中,并且仅仅是追加数据到文件末尾,也就是采用了 顺序写 的机制。

但是,光顺序写其实还是不够的,Kafka同时利用了操作系统的Page Cache,也就是说消息不是写到磁盘上,而是写到缓存中,正是依靠了 顺序写+Page Cache+零拷贝 的机制,Kafka才能有超高的写入性能,单物理机可以做到每秒10W级别的消息写入。

202307312119264691.png

从写Page Cache这个特性也可以看出,虽然Kafka Broker自身是一个JVM进程,但其实不会占用过多JVM内存,而是需要OS分配更多的page cache,以此来缓存更多的消息并异步刷盘。

一、零拷贝

我们来回顾一下使用Kafka的整个流程:

  1. Producer发送一个消息给Kafka Broker;
  2. Kafka接受到消息后,将其持久化到磁盘(可能只是写入Page Cache);
  3. Consumer拉取消息,Kafka读取磁盘上的消息,然后通过网络发送给Consumer。

整个流程涉及多次磁盘读写,如果Kafka真的这么干,就不会有 高吞吐低延迟 的特性了。事实上,Kafka大量使用了 零拷贝 技术,使得消息存储和消费的性能极高。

在了解什么是零拷贝之前,我们先来看下传统的I/O方式。

1.1 普通I/0过程

假设我们有下面的几行代码,JVM程序先从磁盘上读文件,然后通过Socket发送给其它JVM程序:

    // 1.从磁盘读取文件
    File file = new File("xxx.txt");
    RandomAccessFile raf = new RandomAccessFile(file, "rw");         
    byte[] arr = new byte[(int) file.length()];        
    raf.read(arr);   
    
    // 2.通过网络发送数据
    Socket socket = new ServerSocket(8080).accept();        
    socket.getOutputStream().write(arr);

上述[读磁盘数据 -> 网络发送]整个流程一共发生了四次数据拷贝,如下图:

202307312119276172.png

  1. 从用户态切换到内核态,将磁盘上的数据通过 DMA拷贝 到内核缓冲区;
  2. 从内核态切换到用户态,将内核缓冲区的数据拷贝到用户缓冲区(CPU拷贝);
  3. 从用户态切换到内核态,将用户缓冲区的数据拷贝到Socket缓冲区;
  4. 最后,还有一个异步化的过程,将Socket缓冲区数据通过DMA拷贝到网络引擎,发送出去;
  5. 全部完成后,从内核态切换到用户态。

所以说,从本地磁盘读取数据,发生了2次数据拷贝,然后通过网络发送出去,又发生了2次数据拷贝。期间用户态和内核态之间要发生4次切换。所以说,普通的IO操作性能是较低的。

1.2 零拷贝过程

我们再来看下Kafka是如何实现消息的存储和消费的,假设此时消息已经通过异步刷盘,从os cache刷到了磁盘上:

202307312119294243.png

我来说明下上图的流程:

  1. 首先,Kafka Broker从用户态切换到内核态,将磁盘上的数据通过 DMA拷贝 到内核缓冲区;
  2. 从内核缓冲区拷贝数据的一些offset和length文件描述符到Socket缓冲区;
  3. 接着,直接把数据从内核缓冲区拷贝到网络引擎(网卡)里。同时,还从Socket缓冲区里拷贝一些offset和length到网络引擎里去,但是这个offset和length的量很少,几乎可以忽略。

综上所述,通过sendfile方式进行零拷贝时,数据传送只发生在内核态,而且整个过程只进行了2次数据拷贝。

Linux 2.1 版本提供了 sendFile 函数,也就是零拷贝技术,对应于 Java 语言,FileChannal.transferTo()方法的底层实现就是 sendfile方法。


Java 面试宝典是大明哥全力打造的 Java 精品面试题,它是一份靠谱、强大、详细、经典的 Java 后端面试宝典。它不仅仅只是一道道面试题,而是一套完整的 Java 知识体系,一套你 Java 知识点的扫盲贴。

它的内容包括:

  • 大厂真题:Java 面试宝典里面的题目都是最近几年的高频的大厂面试真题。
  • 原创内容:Java 面试宝典内容全部都是大明哥原创,内容全面且通俗易懂,回答部分可以直接作为面试回答内容。
  • 持续更新:一次购买,永久有效。大明哥会持续更新 3+ 年,累计更新 1000+,宝典会不断迭代更新,保证最新、最全面。
  • 覆盖全面:本宝典累计更新 1000+,从 Java 入门到 Java 架构的高频面试题,实现 360° 全覆盖。
  • 不止面试:内容包含面试题解析、内容详解、知识扩展,它不仅仅只是一份面试题,更是一套完整的 Java 知识体系。
  • 宝典详情:https://www.yuque.com/chenssy/sike-java/xvlo920axlp7sf4k
  • 宝典总览:https://www.yuque.com/chenssy/sike-java/yogsehzntzgp4ly1
  • 宝典进展:https://www.yuque.com/chenssy/sike-java/en9ned7loo47z5aw

目前 Java 面试宝典累计更新 400+ 道,总字数 42w+。大明哥还在持续更新中,下图是大明哥在 2024-12 月份的更新情况:

想了解详情的小伙伴,扫描下面二维码加大明哥微信【daming091】咨询

同时,大明哥也整理一套目前市面最常见的热点面试题。微信搜[大明哥聊 Java]或扫描下方二维码关注大明哥的原创公众号[大明哥聊 Java] ,回复【面试题】 即可免费领取。

阅读全文