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

Kafka 日志存储 — 磁盘存储

Kafka 依赖与磁盘来存储和缓存消息,采用文件追加的方式来写入消息。顺序写盘的速度快于随机写内存。

1 磁盘存储

除顺序写入外,Kafka中大量使用了页缓存、零拷贝等技术来进一步提升吞吐性能。

1.1 页缓存

页缓存是操作系统实现的一种磁盘缓存,以此来减少对磁盘I/O的操作。

图 进程读取及写入数据流程

1.1.1 刷盘

将脏页写入到磁盘的过程叫做刷盘。

vm.dirty_background_ratio

当脏页数量达到系统内存的百分之多少之后就会触发刷盘(异步)。默认值为10。

vm.dirty_ratio

当脏页数量达到系统内存的百分之多少之后就立马进行刷盘(同步)。默认值为20。

表 Linux 控制刷盘时机的参数

Kafka同样提供了同步刷盘及间断性强制刷盘的功能,但是不建议使用,刷盘任务应交由操作系统去调配。

1.1.2 未使用进程内的缓存

进程会在其内部缓存处理所需的数据,然后这些数据有可能还缓存在页缓存中,因此同一份数据有可能被缓存了两次。

在Java中,对象的内存开销非常大,通常会是真实数据大小的几倍,空间使用率低下。Java的垃圾回收会随着堆内数据的增多而变得越来越慢。

使用页面缓存可以省去进程内部的缓存消耗,同时通过紧凑的字节码来代替使用对象的方式来节省更多的空间.

此外,即使Kafka服务重启,页缓存还是会保持有效,而进程内的缓存却需要重建。

1.1.3 swap 分区

当物理内存(非磁盘,而是相对于虚拟内存)不够时,Linux会使用磁盘的一部分作为swap分区,将非活跃的进程调入swap分区,来把内存空出来给活跃的进程。

通过vm.swappiness参数来进行调节,其上限为100,表示积极使用swap分区,并把内存上的数据及时地搬运到swap分区中,下限为0,表示任何情况下都不要发生交换。

对于Kafka而言,尽量避免这种内存交换,否则会对它的各方面性能产生很大的负面影响。建议将这个参数值设置为1。

1.2 磁盘I/O流程

图 应用与磁盘I/O操作流程

写操作:用户调用fwrite把数据写入C库标准IObuffer后就返回,写操作通常是异步操作。C库不会立即将数据刷新到磁盘,会将多次小数据量相邻写操作先缓存起来合并,最终调用write一次性写入页缓存。内核的pdflush线程不停检测脏页,判断是否要写到磁盘,如果是,则发起磁盘I/O请求。

读操作:用户调用fread到C库IObuffer中读取数据,如果成功则返回,否则页缓存读取数据,如果成功则返回,否则发起磁盘I/O请求,读取后将数据缓存到页缓存和C库的IObuffer,并返回。读操作是同步操作。

I/O请求:通用块层根据I/O请求构造一个或多个bio(block I/O,阻塞式I/O模型)结构并交给调度层。调度层将bio结构进行排序和合并组织成队列:将一个或多个进程的读操作合并到一起读,将一个或多个进程的写操作合并到一起写,尽可能变随机为顺序,读必须优先满足。

1.2.1 Linux的I/O调度策略

算法

介绍

优缺点

NOOP

No Operation,无操作调度器。采用FIFO(先进先出)策略,按照I/O请求到达的顺序进行处理。在这基础上,会尝试合并相邻(物理地址相邻)的I/O请求:

当一个新的I/O请求到达时,会检查这个请求是否可以和队列种某个请求合并(减少磁盘转动次数)。

优点:低延迟、高吞吐量、简单高效。

缺点:请求饥饿问题、磁盘寻道开销大、缺乏适应性。

CFQ

Completely Fair Queuing,完全公平排队。默认的调度算法。为每个进程单独创建一个队列来管理该进程所产生的请求。根据进程的权重和时间片来调度这些请求。并且将I/O请求按照地址进行排序。

优点:公平性,确保每个进程都能获得公平的I/O带宽。较少了磁盘寻道开销。

缺点:处理大量小I/O请求时有延迟;对优先级高的请求响应不够迅速。

DEADLINE

最后期限。在CFQ基础上,解决了I/O请求“饿死”的情况。除了CFQ本身的I/O队列,还分别为读写提供了FIFO队列。读FIFO队列的最大等待时间为500ms,写FIFO队列的最大等待时间为5s。FIFO队列的优先级要比CFQ队列高。

优点:实时性强、公平性、灵活性。

缺点:复杂度高、资源开销更大

ANTICIPATORY

预期的。上面的算法考虑的焦点在于满足零散I/O请求上,对于连续的I/O请求(比如顺序读),并没有做优化。ANTICIPATORY在DEADLINE的基础上,为每个读I/O都设置了6ms的等待时间窗口,在等待期间OS收到了相邻位置的读请求,则合并请求并处理。

优点:通过预测和合并来减少磁盘的寻道次数和旋转延迟。

缺点:如果非连续读请求较少,则延迟会更长。

表 Linux 的I/O调度策略

请求饥饿:在I/O调度过程种,某些I/O请求由于调度算法的不当处理(无法公平、有效地处理所有请求)而长时间得不到服务,导致请求被“饿死”的现象(长时间等待)。

1.3 零拷贝

将数据直接从磁盘复制到网卡设备中,而不需要经过应用程序。

例如:将磁盘中的图片展示给用户。

正常流程为,将磁盘中的数据复制出来放到内存buf中,然后将这个buf通过套接字(Socket)传输给用户。这个过程中,经历了4次复制。

图 非零拷贝技术的复制过程

图 内核模式下零拷贝技术的复制过程

零拷贝技术通过DMA(Direct Memory Access)技术将文件内容复制到内核模式下的Read Buffer中,然后直接传递到网卡设备。这是在内核模式下实现了零拷贝。


http://www.kler.cn/a/525040.html

相关文章:

  • 中间件安全
  • 【新春特辑】2025年春节技术展望:蛇年里的科技创新与趋势预测
  • CMAKE工程编译好后自动把可执行文件传输到远程开发板
  • 在无sudo权限Linux上安装 Ollama 并使用 DeepSeek-R1 模型
  • [蓝桥杯 2014 省 AB] 蚂蚁感冒
  • 哈工大:LLM高质量嵌入模型KaLM-Embedding
  • LeetCode:40. 组合总和 II(回溯 + 剪枝 Java)
  • Python3 【高阶函数】水平考试:30道精选试题和答案
  • SOME/IP--协议英文原文讲解4
  • 人工智能如何驱动SEO关键词优化策略的转型与效果提升
  • Unity阿里云OpenAPI 获取 Token的C#【记录】
  • Windows程序设计4:API函数URLDownloadToFile和ShellExecuteEx
  • Python3 【函数】:见证算法的优雅与力量
  • 论文阅读(十三):复杂表型关联的贝叶斯、基于系统的多层次分析:从解释到决策
  • 26.useScript
  • 如何将DeepSeek部署到本地电脑
  • Shell特殊状态变量以及常用内置变量总结
  • Kmesh v1.0 正式发布
  • 用JavaScript实现观察者模式
  • 小白爬虫冒险之反“反爬”:无限debugger、禁用开发者工具、干扰控制台...(持续更新)
  • 【16届蓝桥杯寒假刷题营】第2期DAY4
  • 安卓逆向之脱壳-认识一下动态加载 双亲委派(二)
  • 洛谷P3383 【模板】线性筛素数
  • 在Visual Studio Code自带的按键编译无法使用该怎么办
  • JavaScript_01
  • Baklib如何重新定义企业知识管理提升组织效率与创新力