• Kafka 为什么这么快,性能如此优良


    一、磁盘顺序写保证写高性能

    kafka 对硬盘的写入的模式是顺序写,而不是随机 I/O。在顺序写的情况下,速度可与内存持平。
    同时利用了操作系统的页缓存(Page Cache),数据写入缓存后,立即返回,不需等待数据被持久化到磁盘。然后由操作系统决定何时把 Page Cache 的数据真正写入到磁盘中。
    同时利用了 mmap,mmap其实就是把物理上的磁盘文件的一些地址和page cache地址进行一层映射,使得进程像读写硬盘一样读写内存,定时有os帮助我们将数据刷写到磁盘。

    二、零拷贝机制保证读高性能

    在非零拷贝模式下,应用程序想把磁盘数据通过网卡发出去需要以下步骤:

    1. 操作系统将数据从磁盘拷贝到内核区的 page cache;
    2. 用户程序把数据从 page cache 拷贝到用户区缓存;
    3. 用户程序将数据从用户区缓存拷贝到 socket 缓存;
    4. 操作系统将 socket 缓存的数据拷贝到网卡的 buffer 上发送数据。

    如下图所示:

    进行了2次上下文切换和4次系统调用。其实可以省去第 2和 3 步骤,由内核直接读取数据发送到 网卡。

    三、日志分段保存

    kakfa 在磁盘的文件目录布局是:
    主题的日志文件按分区划分为多个文件夹,文件夹命名为-
    以(topic-分区号)作为目录,目录下有 .log 和 .index 和 .timeindex 文件,如下所示:

    -rw-r--r--  1 zhangsan  admin     72 Oct 24 22:15 00000000000000000014.index
    -rw-r--r--  1 zhangsan  admin  41805 Oct 24 22:15 00000000000000000014.log
    -rw-r--r--  1 zhangsan  admin      0 Oct 24 22:15 00000000000000000014.timeindex
    
    -rw-r--r--  1 zhangsan  admin     80 Oct 24 22:15 00000000000000000536.index
    -rw-r--r--  1 zhangsan  admin  41760 Oct 24 22:15 00000000000000000536.log
    -rw-r--r--  1 zhangsan  admin      0 Oct 24 22:15 00000000000000000536.timeindex
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7

    文件夹内的日志文件分为多个 segment,每个 segment 包含三个文件:

    • xxx.log: 消息内容主文件,记录消息内容信息
    • xxx.index: 偏移量索引文件,记录偏移量到消息位置的映射
    • xxx.timeindex: 时间戳索引文件,记录时间戳到偏移量的映射

    首先关注一下每个 segment 的命名,文件名称为20位整数,不够用0填充,数字表示当前 log 文件中第一条消息的偏移量。
    .indedx 文件产生的规则是,每当 .log 文件中写入了 4kb 的消息,则会在 .index 文件中新增一条记录,.index 里面是一种稀疏的索引。
    比如:

    offset: 588 position: 4160
    offset: 640 position: 8320
    offset: 692 position: 12480
    offset: 744 position: 16640
    offset: 796 position: 20800
    
    • 1
    • 2
    • 3
    • 4
    • 5

    假设现在有消费者,需要从 offset 为700的位置消费数据。假设没有索引文件的情况下,需要从 .log 文件的第一行开始依次往下一次遍历查找,性能比较低。
    kafka 的做法是:

    1. 先从跳表中查询出这条日志在哪个日志分段中(Kafka 会在跳表中缓存每个日志分段的起始 offset);
    2. 确定偏移量位置,通过二分法确定相对偏移为 700 这条数据在 692-744 之间,然后根据 692 这条数据的物理位置 12480,直接定位到 log 文件的这条记录;
    3. 依次往下查找,直到找到 offset 为700的这条数据。

    更多内容,可以点击下面的链接访问我的数字花园:
    我的技术数字花园

  • 相关阅读:
    JedisConnectionException: java.net.SocketException: Broken pipe (Write failed) 问题排查
    MySQL单机应用的性能优化
    【面试必问】HTTP与HTTPS的区别以及HTTPS的工作流程
    numpy学习笔记
    代码随想录 Day49 单调栈01 LeetCode LeetCodeT739每日温度 T496 下一个最大元素I
    华为OD机试 - 最长连续子序列 - 双指针(Java 2023 B卷 100分)
    GridSearchCV 工具介绍
    阻塞队列以及阻塞队列的一个使用
    【数据结构】最小生成树(Kruskal算法)
    第三方模块远程注入到软件中引发软件异常的若干实战案例分享
  • 原文地址:https://blog.csdn.net/qq_24434251/article/details/127679454