Ext4日志优化-iJournaling

news2024/12/28 21:03:27

背景

这几年随着SSD等高性能介质的普及,及其在大规模分布式存储系统上的应用。基于Append only的日志写入技术也应用得越来越多,这几天刚好有空,重读了Ext4文件系统的日志部分的内容,也正好看到一篇对Ext4日志技术进行优化的论文,该论文中的优化方案,作为Ext4经典日志技术的补充,随着Linux 5.10内核一起发布,Geek玩家,可以尝尝鲜。

Ext4日志及不足

基础知识

  1. Ext4日志,第一要义是保证文件系统的一致性,第二才是数据的完整性。(言外之意:开启日志,数据也可能会丢)。
  2. Ext4日志,在文件系统中是一个文件,默认Inode号为8,大小为一个块组(128MiB),日志文件通常存储在文件系统分区的中部;当然在格式化文件系统时,可以通过-J参数设置日志的大小。
  3. Ext4支持三种日志模式
  • ordered,日志中只记录元数据,数据写入磁盘后才会提交日志。这是默认模式。
  • journal,日志中同时记录元数据及数据内容,最安全也是最慢的模式,同时会导致延迟分配及Direct-I/O失效。
  • writeback,日志中只记录元数据,但是不保证元数据和数据的写入顺序。(言外之意:元数据提交了,数据可能还没有落盘)。
  1. Ext4日志,可以关闭,即采用无日志模式运行
  2. Ext4日志文件,默认放在文件系统的中部区域,称为内部日志;为提升日志的可靠性,也可以将日志配置在独立的设备上,称为外部日志,你可以在配置及挂载ext4文件系统时,通过-journal-dev参数设置外部日志设备

日志结构

Ext4采用JBD2进行日志管理,日志的详细磁盘结构, 总结如下:

  1. 内部日志
    日志文件由一个超级块和若干日志事务组成,每个日志事务包含一个描述块,若干撤销块和(或)若干数据块,以及一个提交块
    内部日志
  • Block Header: 日志中的每个块都包含一个12字节的通用块头,包括:4字节的魔数,4字节的类型,4字节的事务ID。
  • Superblock:日志超级块(内嵌Block Header),存放在日志文件的头部,占用1024字节,用来记录日志文件的结构信息。
  • Descriptor Block: 描述块(内嵌Block Header),至少36字节,占用一个block,包含一组块标签用来记录事务中数据块的位置,块标签内容会因为JBD2的标志设置的不同而不同,通常包含一个标识,一个块地址以及校验码。
  • Revocation Block:撤销块(内嵌Block Header),至少16字节,占用一个block,包含一组需要撤销的块ID,撤销块用来表明之前的某个日志事务中的块不再需要重放
  • Commit Block:提交块(内嵌Block Header),32字节,占用一个block,通常包含校验码和时间。提交块,作为一个哨兵块,表明日志事务已经落盘
  1. 外部日志
    外部日志与内部日志很类似,只是因为放在了外部设备上,多了一个标准的Ext4超级快(及前置填充)
    外部日志

日志原理

JBD2的操作单位是块(block),提交一个日志的时候,会包含日志事务中的所有块,因此一个逻辑操作可能影响多个块。(言外之意:一个日志事务中可能包含多个变更,也可能包含与本次逻辑操作不相干的变更内容)

背景知识

  • 在Linux系统中,一个典型的文件系统I/O要经过App -> VFS(Page Cache)-> (文件系统)JBD2 -> 块I/O子系统 -> 磁盘。Page Cache中的文件数据由系统在必要时通过回写线程(BDI设备的kworker线程)或者用户fsync回写,JBD2日志缓存中的数据由JBD2线程定时或者用户fsync回写。
  • 在调度层,回写线程(flush)和fsync的I/O优先级不同,fsync调用携带了SYNC标志,优先级更高,所以fsync的I/O会加入到CFQ的同步队列,回写flush的I/O会加入CFQ的异步队列。

下图展示了日志提交,及回写(flush),用户fsync的相关过程
Ext4日志提交

  1. 图(a):用户进程Process1,Process2,Process3分别向文件fileA,fileB,fileC写入内容(缓存在Page Cache),回写线程为脏数据分配数据块(Ext4开启了延迟分配的话,在回写的时候才分配数据块),将相关的inode注册到running状态的日志事务中(如果当前没有running状态的事务,创建一个新的日志事务,然后设置为runing状态),然后flush数据块(1231)到异步队列。
  2. 图(b):图(a)回写继续进行,用户进程Process2更新文件fileB,然后发起了fsync,用户进程被block,fsync做了两个动作:首先更新相应的元数据块并添加到running的日志事务中,然后回写fileB的数据块(2)到同步队列。图(a)中的回写还在继续,fileA的数据块(12)已经持久化到磁盘,fileC的数据块(12)添加到了异步队列。
  3. 图(c):图(b)中的fsync继续进行(还未返回),系统发起了JBD2日志提交,事务状态修改为commiting(如果之前已经有事务处于commiting状态,那么当前的提交会被block), 并等待返回。由于日志事务中包含fileA,fileB,fileC的信息,所以三个文件的脏数据都会被回写。
  4. 图(d):图(c)中的数据回写完成后,日志事务写入到磁盘,状态修改为checkpoint。fsync返回,用户进程Process2返回。

总结

根据上文的分析,我们归纳出Ext4的日志机制有如下的不足,并导致I/O延迟增加

  • JBD2串行事务依赖,为了避免并发提交重叠事务带来的一致性风险,每个时刻只能有一个事务处于commiting状态。
  • JBD2组合事务提交,JBD2事务中可能包含多个不相干的inode,当发起事务提交时,会将所有文件的数据块都提交。
  • JBD2组合事务可能使延迟分配失效,因为组合事务提交的原因,不相干的文件也被提交,导致延迟分配策略失效。

iJournal日志技术

与JBD2块级的日志机制不同,iJournal是一种文件级的日志技术。iJournal已经应用到Linux 5.10,作为JBD2的一个补充,JBD2日志称为标准提交日志,没有变化,新增的iJournal日志称为快速提交日志,核心目的是提升fsync的性能。下面我们一起来看下iJournal的工作原理

核心思想

iJournal用来提升fsync的性能,因此只在调用fsync的时候才会触发。iJournal日志事务保存在iJournal日志区,iJournal将生成的日志事务保存在iJournal日志区,但并不会提交/影响JBD2中的running日志事务,同时iJournal中提交的元数据块,也会继续提交到JBD2日志事务中。iJournal日志事务只包含最基本的用于恢复的文件级元数据,如:Inode项,外部extent结构(非内联在inode的extent)以及相关的目录项,因此比JBD2日志要小得多。

下图展示了通过iJournal恢复块位图的一个示例:通过日志事务中的inode项或者外部extent中记录的extent信息恢复块位图,如图,extent中包含30和31两个数据块,因此可以用于恢复块位图中的第30和31号位。
恢复块问题

日志事务

iJournal用独立于JBD2的区域来保存日志,为了支持多核,采用per-core的设计,即:每个核一个iJournal日志区。下图是iJournal日志事务的格式,包括两种日志事务:

  • 文件日志事务, 包含的是fsync的文件的元数据,
  • 目录日志事务, 包含的是与fsync相关的父目录的元数据。
    iJournal事务

iJournal header:

iJournal日志事务头,占4K,包含一个JBD2日志头(Block Header),4字节的Inode号,256字节的文件Inode结构以及若干块标签。

  • iJournal日志事务与包含同一个文件的JBD2日志事务有相同的事务号,iJournal日志分布在多个日志区,恢复模块根据事务号来鉴别事务顺序。另外,在一个JBD2的running日志事务过程中,可能发生多个文件fsync,因此可能存在多个有相同事务号的iJournal事务,为了解决这些事务的顺序问题,iJournal引入了全局子事务号,该子事务号随着fsync的调用而线性递增。
  • 文件inode号,用来恢复inode表,inode位图及块组描述表。
  • 块标签,每个块标签表示的是日志文件中一个external extent到文件块的映射。进行一致性恢复时,会使用inode结构中的internal extent,块标签,以及external extent来恢复块位图。

文件日志事务

文件日志事务包含的是fsync的文件的元数据,由一个iJournal日志头,若干external extent(如果有)以及一个提交块组成。
文件日志事务中,只包含脏的external extent,为了减少搜索extent树的开销,iJournal的引入,需要对文件系统进行如下的修改:为每个文件维护一个未提交的脏extent列表,在extent创建/删除时对列表进行更新。【每个列表元素占用20字节,看起来开销可接受】。

目录日志事务

目录日志事务,记录的是fsync文件的父目录的更新,有一个iJournal日志头,若干目录项(DE)以及一个提交块组成。举个例子:

创建目录/A,子目录/A/B, fsync文件/A/B/c,这个时候iJournal需要记录目录/A, /A/B,
以及文件/A/B/c的变化。提交日志的时候,也需要将目录也一并提交。

为了跟踪未提交的目录,需要在文件的Inode中添加uncommitted_DE标志。创建文件时,设置该标志,表示文件目录项还未记录在父目录块中。父目录块被JBD2提交后,清除该标志。iJournal在创建fsync日志记录时,会先检查文件inode中的uncommitted_DE标志,如果标志被设置,就会递归的查找未提交的父目录,然后创建目录日志事务,并按照最顶级目录,下一级目录…的顺序将目录记录在目录日志事务中,最后才创建文件日志事务。【注:为了减少解码目录块的时间消耗,目录日志事务中每个DE项会记录完整的目录块】

如果一个fsync的文件,没有外部extent以及父目录DE块被修改,那么所有的信息可以保存在iJournal日志头中,只占用一个块大小。

故障恢复

与JBD2日志不同,iJournal日志只用于恢复与fsync相关的目录和文件。为了简化iJournal的实现,某些场景也是用JBD2日志来实现

  • 对于目录的fsync,用JBD2日志来实现;
  • 对于包含文件硬链接的目录,用JBD2日志来实现;为了处理这种情况,在文件的inode中添加uncommitted_HL标志,当inode中的i_link_count计数因为硬链接增加时,设置该标志。JBD2提交了日志后,清除该标志。fsync调用会检查这个标志,如果该标志被设置,就调用JBD2日志。

进行故障恢复时,恢复模块先扫描JBD2标准日志区,提交那些还未checkpoint的日志事务,同时找到最后提交的日志事务号Max_TxID。然后,扫描iJournal快速日志区,只恢复那些合法的iJournal日志事务:合法的iJournal日志事务是指那些事务号大于Max_TxID的事务,如果一个inode有多个iJournal事务,那么拥有最大子事务号的事务才是合法的。怎么理解,请看下文:

下图(a)显示了一个日志提交场景
日志提交
下图(b)显示了一个文件恢复场景
文件恢复

  1. 图(a),在时刻30,JBD2事务号TxID=n的日志事务被提交,事务号+1,变成TxID=n+1;在事务号TxID=n+1的事务周期内,文件fileB,fileC,fileD发生变化,两个进程分别发起了针对文件fileC,fileD的fsync。
  2. 图(b),iJournal事务号(TxID, sub-TxID)= (n+1, 0)和(n+1, 1)的日志事务分别包含fileC和fileD的已提交日志事务。
  3. 图(a),在事务号TxID=n+1的事务提交前,系统Crash。图(b),因为JBD2事务号TxID=n的事务已提交,所以iJournal事务号TxID=n的事务不合法,所以恢复时,iJournal恢复从事务号TxID=n+1的事务开始。图(a),在TxID=n+1事务期间的文件fileB的变更丢失。

iJournal恢复

因为每个fsync调用会生成一个文件日志事务和若干目录日志事务,如果在处理fsync过程中,发生系统Crash,fsync生成的多个日志事务无法实现原子提交。此外,目录事务中的DE块也包含不相干文件的信息,因此,在进行故障恢复时,并没有直接将DE块复制到文件系统上,而是先识别出发生变化的目录项,如果上述目录项指向的inode可以访问,就用DE块更新文件系统。

图(a)显示了iJournal恢复的初始状态,inode号等于3的文件,包含3个external extent,包含24个数据块;图(b)进行了一些文件操作,首先10个数据块(50-59)及在12号块的external extent结构被删除;接着,追加6个数据块(74-79),在13号块的external extent结构被更新;最后发起fsync。
iJournal恢复-a
iJournal恢复-b
图(c),假定在JBD2提交前,发生了系统Crash。恢复模块,根据iJournal日志,生成inode结构以及external extent树。将生成的inode与文件系统中的inode进行比较,恢复模块通过记录的fsync日志能够识别出文件系统的变化,并应用这些变更恢复系统。12号块的external extent被删除时,JBD2日志记录一个撤销块,用于跳过该日志事务的恢复。同时iJournal也会跳过撤销块的写入。
iJournal恢复-c

效果

根据论文中的测试数据,iJournal在桌面应用,移动应用两个场景下,fsync延迟以及多核带宽性能都有非常显著的改善。

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

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

相关文章

Measuement Comuputing 公司USB-1608GX设备EPICS驱动的安装和调试记录

1、USB-1608GX模块简介 单端输入的管脚图 差分输入管脚图 USB-1608GX模块具有以下功能: 1) 16位模拟输入: 16路单端通道或者8路差分通道。每个通道可编程的范围:-1V-1V,-2V-2V,-5V-5V,-10V-10…

经典数据结构之2-3树

2-3树定义 2-3树,是最简单的B-树,其中2、3主要体现在每个非叶子节点都有2个或3个子节点,B-树即是平衡树,平衡树是为了解决不平衡树查询效率问题,常见的二叉平衡书有AVL树,它虽然提高了查询效率&#xff0c…

Mac AndroidStudio开发环境搭建

Mac AndroidStudio开发环境搭建 1.在Mac上配置环境变量 执行 open ~/.bash_profile (该文件是配置环境变量) 如果提示没有 执行 touch ~/.bash_profile 进行创建 打开文件之后 新增jdk和android sdk 参考蓝色部分需要替换对应内容 #jdk export JAVA_HOME/Library/J…

【100个 Unity实用技能】 | InputField输入框组件实现输入限制,只能输入中文或特殊字符等

🎬 博客主页:https://xiaoy.blog.csdn.net 🎥 本文由 呆呆敲代码的小Y 原创,首发于 CSDN🙉 🎄 学习专栏推荐:Unity系统学习专栏 🌲 游戏制作专栏推荐:游戏制作 &…

tar: invalid option -- ‘z‘

在嵌入式开发过程中,出现tar命令无法识别到z选项,说明我们系统的tar命令版本太旧了,需要进行版本更新 下载地址 ftp://alpha.gnu.org/gnu/tar/ 这里选择下载 tar-1.27.1.tar.gz 我发现这个网址有时候会缺少一些版本,其他版本…

NeRFStudio系列 Part 1:PipeLines概述

前言:Why NeRFStudio? NeRF社区是近两年来计算机领域最活跃的学术社区之一,各种具有milestone意义的算法层出不穷,各位作者的开源工作也做得非常扎实,非常多的工作都自带了code、data、project page。 但是后继者想要在这些伟大的…

gpt3.5和gpt4区别-gpt3.5和gpt4

gpt系列 GPT系列是OpenAI公司开发的一组基于人工智能深度学习技术的自然语言处理模型。GPT代表Generative Pre-trained Transformer,即预训练生成模型。目前,GPT模型已经推出了三代(GPT-1,GPT-2,GPT-3)&am…

【Linux】虚拟机VMware中Centos7系统设置静态ip的详细步骤详解,看这一篇就够啦!

此篇主要讲解一下在VMware中创建centos7之后如何设置静态IP,有时候外部的连接工具要连接过来,需要稳定的一个ip地址,不然老是换ip,我们平时测试练习学习一些东西都会造成阻碍。接下来我使用设置if-ens33文件和nmtui命令的两种方式…

企业绩效管理怎么做?

阅读本文您将了解:1.企业绩效管理是什么;2.企业绩效管理怎么做;3.绩效管理系统的优势所在。 一、绩效管理是什么 绩效考核和绩效管理是企业管理中必须了解和掌握的概念。绩效考核是企业对主要经济和技术指标完成情况按照既定方案进行的考核…

密码安全性和数据合规性

企业有责任妥善存储和共享信息。过去的可怕事件,如雅虎的大规模数据泄露导致数百万用户的敏感信息被泄露,突显了为什么企业主如此担心其组织中的数据安全。 数据泄露不仅会使用户的隐私受到威胁,而且还会对公司的财务和声誉产生不可逆转的影…

​Laravel 使用 MinIO 作为文件存储​

起因 我们的图片资源和其他静态资源都采用 S3 来进行存储,于是我们为了降低代码复杂度,我们在开发和测试阶段用的存储页时线上 S3 环境,一直以来一切都正常运行着。但是突然有一天,在国内的测试服上传文件到 S3 出现了超时的问题…

Vue核心 模板语法 数据绑定

1.3.模板语法 Vue模板语法包括两大类 1.插值语法 功能:用于解析标签体内容 写法:{{xxx}},xxx 是 js 表达式,可以直接读取到 data 中的所有区域 2.指令语法 功能:用于解析标签(包括:标签属性…

Vue3+Typescript+Vitest单元测试+组件Props篇

上一节我们学习了如何测试组件内部的emit事件组件事件测试篇,这一节我们来测试一下组件的props 新增一个组件ZmTag 非常简单,就是可以接受三个参数,然后我们分别来测试三个参数传入的效果 import { defineComponent } from "vue"…

Python GUI设计——Python语言介绍

作者简介:一名云计算网络运维人员、每天分享网络与运维的技术与干货。 座右铭:低头赶路,敬事如仪 个人主页:网络豆的主页​​​​​​ 写在前面 本Python专栏主要讲解 PythonGUI设计 tkinter从入门到实践 系列,本…

PHP实现使用函数实现对数组进行排序

目录 前言 一、使用函数实现对数组进行排序 1.1运行流程(思想) 1.2代码段 1.3运行截图 前言 1.若有选择,可实现在目录里进行快速查找; 2.本弹窗界面可以根据简单的要求实现一使用功能。同时可以实现自定义的设置&#xff1…

最受信任的低代码平台排行榜

近年来,随着数字化转型的兴起,低代码平台获得了大量关注。它允许用户在几乎没有编码知识的情况下创建应用程序,从而使企业能够简化其流程并提高效率。随着低代码平台的日益流行,要确定哪些平台最可靠、最值得信赖并非易事。在本文…

三步配置轻量级服务器nginx

这里写目录标题 一 nginx及其应用场景1.什么是nginx2.应用场景背诵 二 nginx的配置安装1.选择nginx版本2. 安装配置环境3.安装nginx4.启动nginx 三 访问 一 nginx及其应用场景 1.什么是nginx 一款轻量级的Web服务器,反向代理服务器,以及电子邮件代理服…

16.props

props是组件的自定义属性,可以提高组件的复用性,比如 做点击计数器的时候,我可以让计数器组件在A处赋初始值10,在B处赋初始值20 目录 1 基本用法 2 给默认值 default 3 值类型 type 4 是否必填 required 1 基本用法 pr…

【计算机网络】网络命令的使用

文章目录 一、实验目的二、实验工具三、实验要求四、实验过程01 ping 命令的使用应用1:验证本地计算机上是否正确安装了 TCP/IP 协议应用2:测试某个目的主机可达性应用3:键入 ping,查看 ping 的其他参数含义 02 netstat 命令的典型…

求你看完再去面试,涨薪必备分布式事务小抄,狂怼面试官~

分布式事务就是指事务的参与者、支持事务的服务器、资源服务器以及事务管理器分别位于不同的分布式系统的不同节点之上。简单的说,就是一次大的操作由不同的小操作组成,这些小的操作分布在不同的服务器上,且属于不同的应用,分布式…