1 概述

浪潮信息KOS是浪潮信息基于Linux Kernel、OpenAnolis等开源技术自主研发的一款服务器操作系统,支持x86、ARM等主流架构处理器,性能和稳定性居于行业领先地位,具备成熟的 CentOS 迁移和替换能力,可满足云计算、大数据、分布式存储、人工智能、边缘计算等应用场景需求。详细介绍见官网链接https://www.ieisystem.com/kos/product-kos-xq.thtml?id=12126

典型故障排查

2 文件系统损坏修复全流程(xfs_repair

目前网上出现大量的主机输入输出错误,原因是由于主机文件系统损坏。一线人员大部分采用的是umont 和 mount的方式恢复,这种恢复方式不能真正修复已经损坏的文件系统,在后续使用过程中,仍然会再次出现主机端输入输出错误。

2.1 需要修复的场景

1 主机侧发现存在文件系统不可读写的情况,也可以通过查看主机端日志来确认是否有文件系统异常发生: xfs_force_shutdown 、I/O error
2 出现异常停电,供电恢复正常,主机和阵列系统重起之后
3 存储介质故障:出现LUN失效、RAID失效、以及IO超时或者出现慢盘,对慢盘进行更换,系统恢复正常之后
4 传输介质故障:如光纤、网线等损坏等,数据传输链路断开后又恢复正常之后

2.2 检查文件系统

注:检查文件系统必须保证将文件系统umount成功。

在根目录下输入“xfs_ncheck /dev/sdd(盘符);echo $?”(注意:在执行 此命令之前,必须将文件系统umount,否则会出现警告信 “xfs_ncheck: /dev/sdd contains a mounted and writable filesystem ”)敲回车键,查看命令执行返回值:0表示正常,其他为不正常,说明文件系统 损坏,需要修复。

例如:xfs_ncheck /dev/vdc3; echo $?

2.3 修复过程

注:修复时需要暂停主机侧的业务,umount 和 mount 无法修复文件系统 。

先umount要修复的文件系统的分区

然后输入 “xfs_repair /dev/sdd(盘符)”执行修复命令。

xfs_ncheck /dev/sdd; echo $?

如果为0===》成功修复。

如果不为0===》没有成功:请执行xfs_repair –L /dev/sdd命令,再执 行xfs_repair(反复多修复几次)

2.4 xfs常用命令

xfs_admin 调整 xfs 文件系统的各种参数
xfs_copy 拷贝 xfs 文件系统的内容到一个或多个目标系统(并行方式)
xfs_db 调试或检测 xfs 文件系统(查看文件系统碎片等)
xfs_check 检测 xfs 文件系统的完整性
xfs_bmap 查看一个文件的块映射
xfs_repair 尝试修复受损的 xfs 文件系统
xfs_fsr 碎片整理
xfs_quota 管理 xfs 文件系统的磁盘配额
xfs_metadump 将 xfs 文件系统的元数据 (metadata) 拷贝到一个文件中
xfs_mdrestore 从一个文件中将元数据 (metadata) 恢复到 xfs 文件系统
xfs_growfs 调整一个 xfs 文件系统大小(只能扩展)
xfs_logprint print the log of an XFS filesystem
xfs_mkfile create an XFS file
xfs_info expand an XFS filesystem
xfs_ncheck generate pathnames from i-numbers for XFS
xfs_rtcp XFS realtime copy command
xfs_freeze suspend access to an XFS filesystem
xfs_io debug the I/O path of an XFS filesystem

2.5 具体应用

查看文件块状况: xfs_bmap -v sarubackup.tar.bz2

查看磁盘碎片状况: xfs_db -c frag -r /dev/vdc3

文件碎片整理: xfs_fsr sarubackup.tar.bz2

磁盘碎片整理: xfs_fsr /dev/vdc3

2.6 最后方法

损失部分数据的修复方法

根据打印消息,修复失败时:
先执行xfs_repair -L /dev/sdd(清空日志,会丢失文件),再执行xfs_repair /dev/sdd,再执行xfs_check /dev/sdd 检查文件系统是否修复成功。

说明:-L是修复xfs文件系统的最后手段,慎重选择,它会清空日志,会丢失用户数据和文件。

备注:

在执行xfs_repair操作前,最好使用xfs_metadump工具保存元数据,一旦修复失败,最起码可以恢复到修复之前的状态。

3 inode耗尽问题的预防与处理

在 Linux 操作系统中,inode 是文件系统中的一个重要概念,它用于唯一标识文件系统中的每个文件或目录。inode 的耗尽通常会导致系统无法创建新的文件或目录,这对于系统的正常运行是至关重要的。本章节将探讨导致 inode 耗尽的原因,并提出一些可能的解决策略,以及预防方案,以帮助系统管理员更好地管理和维护文件系统。

3.1 inode的定义

Linux系统下文件数据储存在"块"中,文件的元信息,例如文件的创建者、文件的创建日期、文件的大小等。这种储存文件元信息的区域就叫做inode,中文译名为"索引节点"。

inode也占用硬盘空间,硬盘格式化的时候,操作系统自动将硬盘分成两个区域。一个是数据区,存放文件数据;另一个是inode区(inode table),存放inode所包含的信息。

每个inode节点的大小,一般是128字节或256字节。inode节点的总数,在格式化时就给定,一般是每1KB或每2KB就设置一个inode。假定在一块1GB的硬盘中,每个inode节点的大小为128字节,每1KB就设置一个inode,那么inode table的大小就会达到128MB,占整块硬盘的12.8%。

3.2 inode 的组成

inode 通常包含以下信息:

inode号 文件在文件系统中的唯一标识符。
文件类型 指出是文件还是目录。
权限 文件或目录的访问权限,如读、写、执行。
链接数 指向该 inode 的硬链接数量。
所有者ID 文件所有者的用户 ID。
组ID 文件所有者的组 ID。
大小 文件大小,以字节为单位。
块大小 文件系统分配给文件的数据块的大小。
时间戳 文件的创建时间、最后访问时间和最后修改时间。
数据块指针 指向文件数据实际存储位置的数据块指针。

3.3 inode 的作用

inode 是文件系统高效管理文件的关键。当用户访问文件时,系统通过 inode 号快速定位到文件的数据块,而不需要遍历整个文件系统。这样可以显著提高文件访问速度,尤其是在大型文件系统中。此外,inode 还允许实现文件的硬链接,因为硬链接实际上是指向相同 inode 的多个文件名。

3.4 inode 耗尽的原因分析

inode 耗尽通常是由于文件系统的设计和管理不当导致的。以下是一些常见的导致 inode 耗尽的原因:

文件数量过多 在文件系统中,每个文件或目录都需要一个 inode。如果一个文件系统中有大量的文件或目录,那么 inode 的数量可能会迅速耗尽。特别是在一些用于存储大量小文件的系统中,如邮件服务器或版本控制系统,这个问题尤为突出。
硬链接的使用 硬链接是指向同一 inode 的多个文件名。每个硬链接都会增加 inode 的链接数。如果一个文件被频繁地创建硬链接,而没有相应的删除,那么即使文件被删除,其 inode 仍然被占用,导致 inode 无法被回收。
文件系统类型 不同的文件系统类型对 inode 的分配和管理策略不同。例如,ext4 文件系统在格式化时会预先分配一定数量的 inode。如果分配的 inode 数量不足,那么在文件系统使用过程中可能会出现 inode 耗尽的情况。
系统漏洞或错误配置 系统漏洞或错误配置也可能导致 inode 的异常使用。例如,某些应用程序可能会因为编程错误而创建大量临时文件,或者配置错误导致文件系统参数设置不当,从而加速 inode 的消耗。
文件系统损坏 文件系统损坏可能会破坏 inode 的分配记录,导致无法正确释放已删除文件的 inode,或者错误地分配 inode,从而引起 inode 耗尽的问题。

3.5 检测与诊断 inode 耗尽的方法

为了有效管理和维护 Linux 文件系统,系统管理员需要能够及时检测和诊断 inode 耗尽的问题。以下是一些常用的方法和命令,用于检测和诊断 inode 的使用情况。

查看磁盘空间使用情况,使用 df 命令

查看inodess使用情况,使用df -i命令

这条命令会显示系统中每个文件系统的 inode 总数、已使用 inode 数、可用 inode 数以及使用百分比。

使用 find 命令

find 命令可以用来查找文件系统中占用大量 inode 的文件或目录。例如,以下命令会查找当前目录及其子目录下所有大于 10MB 的文件:

find . -type f -size +10M -exec ls -lh {} \;

检查日志文件

系统日志文件(如 /var/log/syslog 或 /var/log/messages)可能会记录关于文件系统的错误信息,包括 inode 耗尽的警告或错误。定期检查这些日志文件可以帮助诊断问题。

3.6 预防与解决 inode 耗尽的策略

inodes的大小在磁盘格式化分区时确定,跟分区的大小相关,分区越大,inodes越大,反之亦然。

linux操作系统根目录一般分区比较小,如果有定时性的小文件产生而又未及时清理,则很容易造成inodes占满。

inodes占满解决步骤:

查看文件最多的目录

for i in /*; do echo $i; find $i | wc -l; done

如果确定目录范围,把/*写的具体点

最终发现是/var/spool/postfix/maildrop目录下小文件过多,原因如下:

由于linux在执行cron时,会将cron执行脚本中的output和warning信息,都会以邮件的形式发送给cron所有者。由于客户环境中的sendmail和postfix没有正常运行,邮件发送不成功,导致全部小文件都堆积在maildrop目录下,另由于缺乏自动清理的机制,故此目录下堆积了大量的文件。

经过排查root用户下发现有个每分钟进行一次时钟同步的定时任务,该定时任务每分钟产生一个小文件。

删除大量文件

ls | xargs -n 1000 rm -rf

需要使用xargs命令,不然会删除失败。

设置方面

在crontab -e 第一行增加MAILTO="" ,就没有文件产生啦

重定向

对定时任务设置定向输出文件,不需要日志输出的定时任务可以将日志重定向到/dev/null,如下:

*/10 * * * * /tmp/test.sh >/dev/null 2>&1

定时清理文件

find 目录 -type f -mtime +30 | xargs -n 1000 rm -f

监控inodes的使用

备注:应注意crontab的写法和产生的文件的定时清理

3.7 实际案例分析

邮件服务器 inode 耗尽

背景:一个邮件服务器在运行过程中遇到了 inode 耗尽的问题,导致无法接收和发送邮件。

原因分析:邮件服务器在处理大量邮件时,会在特定的目录下生成大量的临时文件。如果这些临时文件没有被正确删除,或者邮件服务器软件存在 bug 导致不断生成新文件,inode 的数量就会迅速减少。

解决策略:

清理临时文件 定期检查邮件服务器生成的临时文件目录,并清理这些文件。
优化邮件服务器配置 调整邮件服务器配置,减少临时文件的使用,或者确保文件在不再需要时被正确删除。
监控和告警 实施监控系统,当 inode 使用率达到一定阈值时发送告警,以便及时处理。

版本控制系统 inode 耗尽

背景:一个使用版本控制系统(如 Git)的项目组发现,随着项目的发展,版本控制库所在的文件系统 inode 数量逐渐减少。

原因分析:版本控制系统在处理版本变更时,会生成大量的元数据文件。如果项目组频繁进行提交和分支操作,文件系统中会产生大量的文件和目录,从而导致 inode 的快速消耗。

解决策略:

定期清理旧版本 定期删除不再需要的旧版本和分支,以释放 inode。
使用更高效的存储策略 考虑使用支持 inode 高效管理的文件系统,或者优化版本控制系统的存储策略。
迁移到更大的文件系统 如果 inode 数量确实不足,可以考虑迁移到具有更多 inode 的文件系统。

通过上述案例分析,我们可以看到,inode 耗尽的问题通常是由于文件系统的使用模式和管理策略不当导致的。通过合理规划、监控、优化配置和及时清理,可以有效地避免和解决 inode 耗尽的问题。

4 处理僵尸IO请求的实战步骤

4.1 僵尸进程

当 iowait 升高时,进程很可能因为得不到硬件的响应,而长时间处于不可中断状态。从 ps 或者 top 命令的输出中,你可以发现它们都处于 D 状态,也就是不可中断状态(Uninterruptible Sleep)。既然说到了进程的状态,进程有哪些状态你还记得吗?我们先来回顾一下。

top 和 ps 是最常用的查看进程状态的工具,我们就从 top 的输出开始。下面是一个 top 命令输出的示例,S 列(也就是 Status 列)表示进程的状态。从这个示例里,你可以看到 R、D、Z、S、I 等几个状态,它们分别是什么意思呢?

R Running 或 Runnable 的缩写,表示进程在 CPU 的就绪队列中,正在运行或者正在等待运行
D Disk Sleep 的缩写,也就是不可中断状态睡眠(Uninterruptible Sleep),一般表示进程正在跟硬件交互,并且交互过程不允许被其他进程或中断打断
Z Zombie 的缩写,如果你玩过“植物大战僵尸”这款游戏,应该知道它的意思。它表示僵尸进程,也就是进程实际上已经结束了,但是父进程还没有回收它的资源(比如进程的描述符、PID 等)
S Interruptible Sleep 的缩写,也就是可中断状态睡眠,表示进程因为等待某个事件而被系统挂起。当进程等待的事件发生时,它会被唤醒并进入 R 状态
I Idle 的缩写,也就是空闲状态,用在不可中断睡眠的内核线程上。前面说了,硬件交互导致的不可中断进程用 D 表示,但对某些内核线程来说,它们有可能实际上并没有任何负载,用 Idle 正是为了区分这种情况。要注意,D 状态的进程会导致平均负载升高, I 状态的进程却不会

第一个是 T 或者 t,也就是 Stopped 或 Traced 的缩写,表示进程处于暂停或者跟踪状态。

向一个进程发送 SIGSTOP 信号,它就会因响应这个信号变成暂停状态(Stopped);再向它发送 SIGCONT 信号,进程又会恢复运行(如果进程是终端里直接启动的,则需要你用 fg 命令,恢复到前台运行)。

而当你用调试器(如 gdb)调试一个进程时,在使用断点中断进程后,进程就会变成跟踪状态,这其实也是一种特殊的暂停状态,只不过你可以用调试器来跟踪并按需要控制进程的运行。另一个是 X,也就是 Dead 的缩写,表示进程已经消亡,所以你不会在 top 或者 ps 命令中看到它。

如果系统或硬件发生了故障,进程可能会在不可中断状态保持很久,甚至导致系统中出现大量不可中断进程。这时,你就得注意下,系统是不是出现了 I/O 等性能问题。

再看僵尸进程,这是多进程应用很容易碰到的问题。正常情况下,当一个进程创建了子进程后,它应该通过系统调用 wait() 或者 waitpid() 等待子进程结束,回收子进程的资源;而子进程在结束时,会向它的父进程发送 SIGCHLD 信号,所以,父进程还可以注册 SIGCHLD 信号的处理函数,异步回收资源。

如果父进程没这么做,或是子进程执行太快,父进程还没来得及处理子进程状态,子进程就已经提前退出,那这时的子进程就会变成僵尸进程。换句话说,父亲应该一直对儿子负责,善始善终,如果不作为或者跟不上,都会导致“问题少年”的出现。

通常,僵尸进程持续的时间都比较短,在父进程回收它的资源后就会消亡;或者在父进程退出后,由 init 进程回收后也会消亡。

一旦父进程没有处理子进程的终止,还一直保持运行状态,那么子进程就会一直处于僵尸状态。大量的僵尸进程会用尽 PID 进程号,导致新进程不能创建,所以这种情况一定要避免。

4.2 分析

ps aux | grep /app #查看启动的APP

状态分别是 Ss+ 和 D+。其中,

S 表示可中断睡眠状态,D 表示不可中断睡眠状态,

s 表示这个进程是一个会话的领导进程,而 + 表示前台进程组。(也可通过命令查询man ps )

进程组表示一组相互关联的进程,比如每个子进程都是父进程所在组的成员

而会话是指共享同一个控制终端的一个或多个进程组。

4.3 汇总

第一点,iowait 太高了,导致系统的平均负载升高,甚至达到了系统 CPU 的个数。

第二点,僵尸进程在不断增多,说明有程序没能正确清理子进程的资源。

大量不可中断进程和僵尸进程的处理方法

现象:

iowait太高,导致平均负载升高,并且达到了系统CPU的个数

僵尸进程不断增多

分析过程:

1.先分析iowait升高的原因

一般iowait升高,可能的原因是i/o问题

用dstat 命令同时查看cpu和i/o对比情况(如 dstat 1 10 间隔1秒输出10组数据),通过结果可以发现iowait升高时,磁盘读请求(read)升高

所以推断iowait升高是磁盘读导致

定位磁盘读的进程,使用top命令查看处于不可中断状态(D)的进程PID

查看对应进程的磁盘读写情况,使用pidstat命令,加上-d参数,可以看到i/o使用情况(如 pidstat -d -p 1 3),发现处于不可中断状态的进程都没有进行磁盘读写

继续使用pidstat命令,但是去掉进程号,查看所有进程的i/o情况(pidstat -d 1 20),可以定位到进行磁盘读写的进程。我们知道进程访问磁盘,需要使用系统调用

下面的重点就是找到该进程的系统调用

使用strace查看进程的系统调用 strace -p

ps aux | grep 如果发现进程处于Z状态,说明已经变成了僵尸进程,不能进行系统调用分析了

既然top和pidstat都不能找出问题,使用基于事件记录的动态追踪工具

操作:

系统上运行 perf record -g ,执行一会儿按ctrl+c停止

执行perf report进一步分析,看有没有I/O操作

僵尸进程出现的原因是父进程没有回收子进程的资源出现的。解决办法是找到父进程,在父进程中处理,使用pstree查父进程,然后查看父进程的源码检查wait()/waitpid()的调用或SIGCHLD信号处理函数的注册

性能问题诊断与优化

5 识别IOwait的十八种姿势

5.1 什么是 iowait 以及它如何影响 Linux 性能

I/O 等待或者 iowait、wait、wa、%iowait 或 wait% 通常由 top、sar、atop 等 Linux 命令行系统监控工具显示。就其本身而言,它是让我们深入窥探 Linux 系统性能的众多性能统计数据之一。

什么是 I/O 等待?

I/O 等待适用于 Unix 和所有基于 Unix 的系统,包括 macOS、FreeBSD、Solaris 和 Linux。

I/O 等待 (iowait) 是 CPU(或多个 CPU)空闲的时间百分比,在此期间系统有待处理的磁盘 I/O 请求。(来源:man sar)top man 手册页给出了这个简单的解释:"I/O 等待 = 等待 I/O 完成的时间。" 换句话说,I/O 等待的存在告诉我们系统空闲时它可以处理未完成的请求。

在使用 Linux top 和其他工具时,你会注意到 CPU(及其核心)在以下状态下运行:us(用户态)、sy(内核态)、id(空闲)、ni(nice)、si(软中断)、hi(硬中断)、st(steal)和 wa(等待)。其中,用户态、内核态、空闲状态和等待状态的值加起来应为 100%。请注意,"idle" 和 "wait" 是不同的。"idle" CPU 表示没有工作负载存在,而另一方面,"wait" (iowait) 表示 CPU 何时处于空闲状态等待未完成的请求。

如果 CPU 空闲,内核将确定任何来自 CPU 的未完成 I/O 请求(比如 SSD 或 NFS)。如果有,则 "iowait" 计数器递增。如果没有任何待处理的请求,则 "idle" 计数器会增加。

I/O 等待和 Linux 服务器性能

值得注意的是, iowait 有时可以指示吞吐量瓶颈,而在其他时候,iowait 可能完全没有意义。有可能拥有高 iowait 的健康系统,但也可能有完全没有 iowait 的存在瓶颈的系统。

I/O 等待只是 CPU / CPU 核心的指示状态之一。高 iowait 意味着你的 CPU 正在等待请求,但你需要进一步调查以确认来源和影响。

例如,服务器存储(SSD、NVMe、NFS 等)几乎总是比 CPU 性能慢。因此,I/O 等待可能会产生误导,尤其是涉及到随机读/写工作负载时。这是因为 iowait 仅测量 CPU 性能,而不测量存储 I/O。

虽然 iowait 表明 CPU 可以处理更多的工作负载,但根据服务器的工作负载以及负载如何执行计算或使用存储 I/O,并不总是可以解决 I/O 等待。或者实现接近于零的值是不可行的。

根据最终用户体验、数据库查询健康状况、事务吞吐量和整体应用程序健康状况,你必须决定报告的 iowait 是否表明 Linux 系统性能不佳。

例如,如果你看到 1% 到 4% 的低 iowait,然后将 CPU 升到 2 倍的性能,iowait 也会增加。具有相同存储性能的 2 倍更快的 CPU = ~ 2 倍的等待时间。你需要考虑你的工作负载来确定应该首先关注哪些硬件。

监控和减少 I/O 等待相关问题

让我们看看一些用于监视 Linux 上的 I/O 等待的有价值的工具。

5.2 减少 I/O 等待相关问题

采取以下步骤减少与 I/O 等待相关的问题:

1 优化应用程序的代码和数据库查询。这可以大大降低磁盘读/写的频率。这应该是你的第一个方法,因为应用程序越高效,在硬件上的长期花费就越少。
2 使 Linux 系统和软件版本保持最新。这不仅对安全性更好,而且通常情况下,最新支持的版本会提供显着的性能改进,无论是 Nginx、Node.js、PHP、Python 还是 MySQL。
3 确保有空闲的可用内存。足够的空闲内存,以便大约一半的服务器内存用于内存缓冲区和缓存,而不是交换和换页到磁盘。当然,这个比例会因情况而异。因此,请确保你没有交换,并且内核缓存压力不会因缺少可用内存而变高。
4 调整系统、存储设备和 Linux 内核以提高存储性能和使用寿命。
5 如果一切都失败了:将存储设备升级到更快的 SSD、NVMe 或其他高吞吐量存储设备。

5.3 top命令显示iowait (wa)非常高时怎么排查

当 top 命令显示 iowait (wa) 非常高时,表示系统正在等待 I/O 操作完成。要确定是磁盘 I/O 还是网络 I/O 导致的等待,可以使用以下工具和方法进行进一步排查。

使用 iostat 检查磁盘 I/O

iostat 是一个专门用于监控磁盘 I/O 的工具,可以显示磁盘的读写速度和等待时间。

安装 iostat(如果未安装):

yum install sysstat

使用 iostat 查看磁盘 I/O:

iostat -x 1

-x:显示扩展统计信息。

1:每秒刷新一次。

关键指标:

%util 磁盘利用率。如果接近 100%,表示磁盘 I/O 是瓶颈。
await 平均 I/O 等待时间(毫秒)。如果较高,表示磁盘响应慢。
r/s 和 w/s 每秒的读写操作数。

如果 %util 和 await 较高,说明磁盘 I/O 是导致 iowait 高的原因。

使用 iotop 检查磁盘 I/O

iotop 是一个实时监控磁盘 I/O 的工具,可以显示每个进程的磁盘读写情况。

安装 iotop(如果未安装):

yum install iotop

使用 iotop:

查看哪些进程正在大量读写磁盘。

如果某些进程的磁盘读写量(DISK READ 和 DISK WRITE)非常高,说明它们可能是导致磁盘 I/O 瓶颈的原因。

使用 dstat 综合检查

dstat 是一个多功能工具,可以同时监控 CPU、磁盘、网络等资源。

安装dstat:

yum install dstat

使用 dstat:

查看 CPU、磁盘、网络等资源的实时使用情况。

如果磁盘或网络的使用率非常高,说明它们可能是导致 iowait 高的原因。

5.4 总结

iowait 统计数据是一个有用的性能统计数据,可用于监控 CPU 利用率健康状况。当 CPU 空闲并且可以执行更多计算时,它会通知系统管理员。然后,我们可以使用可观察性、基准测试和跟踪工具(例如上面列出的那些工具)来综合了解系统的整体 I/O 性能。你的主要目标应该是消除因等待磁盘、NFS 或其他与存储相关的 I/O 而直接导致的任何 iowait。

6 使用SystemTap分析锁竞争

6.1 SystemTap简介

SystemTap 是一个强大的工具,用于在不修改内核源代码的情况下,对 Linux 内核进行监控和调试。它允许你编写脚本(通常是使用 Stap 语言),来监视和分析系统运行时的行为。想使用 SystemTap 来分析 Linux 文件系统的锁竞争问题,可以按照以下步骤进行:

安装 SystemTap

安装依赖

yum install gcc make elfutils-libelf-devel rpm-devel nss-devel python3-devel

下载软件包

https://sourceware.org/systemtap/ftp/releases/下载systemtap-4.8.tar.gz

https://sourceware.org/elfutils/ftp/0.176/下载elfutils-0.176.tar.bz2

上传至服务器并解压

tar -zxvf systemtap-4.8.tar.gz

tar -xjf elfutils-0.176.tar.bz2

cd到systemtap-4.8目录开始编译安装

./configure --with-elfutils=./elfutils-0.176

make all

make install

mv /usr/bin/stap /usr/bin/stap.bak

mv stap /usr/bin/

stap -V

6.2 理解文件系统锁

在分析之前,需要了解 Linux 文件系统的锁机制,了解哪些操作会触发锁的获取和释放是非常重要的。

Linux文件系统的锁机制主要包括建议性锁强制性锁‌。建议性锁要求进程显式地检查锁的存在并尊重已有的锁,而强制性锁则由内核强制执行,当一个文件被上锁进行写入操作时,内核会阻止其他进程对该文件进行读写操作‌。

强制性锁

强制性锁是由内核执行的锁,当一个进程对文件设置了强制性锁后,其他进程试图对该文件进行读写操作时会被阻塞,直到锁被释放。这种锁主要用于保护文件的完整性,防止数据损坏。在Linux中,实现强制性锁的函数主要有fcntllockf。fcntl函数提供了细粒度的文件锁控制,可以用来实现强制性锁。其函数原型如下:

其中,cmd参数可以取以下值:

F_SETLKW 设置锁并等待,如果无法立即获取锁,则阻塞直到锁可用。
F_SETLK 设置锁但不等待,如果无法立即获取锁,则返回错误。
F_GETLK 获取锁状态‌。

建议性锁

建议性锁要求每个使用上锁文件的进程都要检查是否有锁存在,并且尊重已有的锁。在一般情况下,内核和系统不使用建议性锁,而是依靠程序员遵守这个规定。实现建议性锁的函数有lockf()和fcntl()。lockf函数用于对文件施加建议性锁,其函数原型如下:

其中,operation参数可以取以下值:

LOCK_SH 共享锁,允许多个进程对同一文件读取,不允许写入。
LOCK_EX 排他锁(写锁),确保只有一个进程能够写入文件。
LOCK_UN 解锁操作,释放锁。
LOCK_NB 非阻塞锁标志,与LOCK_SH或LOCK_EX组合使用,如果无法立即加锁,则返回错误并设置errno为EWOULDBLOCK‌。

6.3 编写 SystemTap 脚本

创建一个 SystemTap 脚本来跟踪文件系统的锁操作。以下是一个基本的示例,用于探测通用VFS锁调用:

global lock_acquires, lock_releases

probe kernel.function("__lock_buffer").entry {

lock_acquires++

}

probe kernel.function("unlock_buffer").entry {

lock_releases++

}

probe timer.ms(1000) {

printf("Lock Acquires: %d\n", lock_acquires)

printf("Lock Releases: %d\n", lock_releases)

lock_acquires = 0

lock_releases = 0

}

这个脚本会监控__lock_buffer和unlock_buffer函数的调用次数,并每秒打印一次这些次数。

6.4 运行 SystemTap 脚本

保存你的脚本到一个文件中,例如 fs_locks.stp,然后使用以下命令运行它:

stap fs_locks.stp

运行之前需要先下载一个内核devel包并安装,如我们这里下载安装kernel-devel-4.19.91-26.6.26.kos5.x86_64.rpm

再运行脚本

6.5 分析输出

观察输出的锁获取和释放次数,以识别是否存在频繁的锁竞争。如果发现锁竞争非常高,可能需要进一步分析哪些操作导致了这些锁的频繁获取和释放。

6.6 深入分析

如果你发现某些特定的函数或操作导致锁竞争,你可以进一步细化你的 SystemTap 脚本,例如跟踪特定函数的调用路径或参数:

probe kernel.function("some_specific_function").call {

printf("Function called: %s\n", probefunc())

}

7 文件系统性能优化

由于各种的I/O负载情形各异,Linux系统中文件系统的缺省配置一般来说都比较中庸,强调普遍适用性。然而在特定应用下,这种配置往往在I/O性能方面不能达到最优。因此,如果应用对I/O性能要求较高,除了采用性能更高的硬件(如磁盘、HBA卡、CPU、MEM等)外,我们还可以通过对文件系统进行性能调优,来获得更高的I/O性能提升。总的来说,主要可以从三个方面来做工作:

1 Disk相关参数调优
2 文件系统本身参数调优
3 文件系统挂载(mount)参数调优

当然,负载情况不同,需要结合理论分析与充分的测试和实验来得到合理的参数。下面以SATA磁盘上的EXT3文件系统为例,给出Linux文件系统性能优化的一般方法。请根据自身情况作适合调整。

7.1 Disk相关参数

Cache mode:启用WCE=1(Write Cache Enable), RCD=0(Read Cache Disable)模式

启用写缓存

hdparm -W 1 /dev/sda

禁用读缓存

hdparm -R 0 /dev/sda

Linux I/O scheduler算法

经过实验,在重负载情形下,deadline调度方式对squidI/O负载具有更好的性能表现。其他三种为noop(fifo), as, cfq,noop多用于SAN/RAID存储系统,as多用于大文件顺序读写, cfq适于桌面应用。

echo deadline > /sys/block/vdc/queue/scheduler

deadline调度参数

对于redhat linux建议 read_expire = 1/2 write_expire,对于大量频繁的小文件I/O负载,应当这两者取较小值。更合适的值,需要通过实验测试得到。

echo 500 > /sys/block/vdc/queue/iosched/read_expire

echo 1000 > /sys/block/vdc/queue/iosched/write_expire

readahead 预读扇区数

预读是提高磁盘性能的有效手段,目前对顺序读比较有效,主要利用数据的局部性特点。比如在我的系统上,通过实验设置通读256块扇区性能较优。

blockdev --setra 256 /dev/vdc

7.2 EXT3文件系统参数

block size = 4096 (4KB)

mkfs.ext3 -b指定,大的数据块会浪费一定空间,但会提升I/O性能。EXT3文件系统块大小可以为1KB、2KB、4KB。

如:

inode size

这是一个逻辑概念,即一个inode所对应的文件相应占用多大物理空间。mkfs.ext3 -i指定,可用文件系统文件大小平均值来设定,可减少磁盘寻址和元数据操作时间。

推荐值:

如:

reserved block

mkfs.ext3 -m指定,缺省为5%,可调小该值以增大部分可用存储空间。

如:

disable journal

对数据安全要求不高的应用(如web cache),可以关闭日志功能,以提高I/O性能。

tune2fs -O^has_journal /dev/vdc3

7.3 mount参数

noatime, nodirtime 访问文件目录,不修改访问文件元信息,对于频繁的小文件负载,可以有效提高性能。
async 异步I/O方式,提高写性能。
data=writeback (if journal) 日志模式下,启用写回机制,可提高写性能。数据写入顺序不再保护,可能会造成文件系统数据不一致性,重要数据应用慎用。
barrier=0 (if journal) barrier=1,可以保证文件系统在日志数据写入磁盘之后才写commit记录,但影响性能。重要数据应用慎用,有可能造成数据损坏。

可依据以上三块调优方向的方法并根据自身情况进行调整,来获得更高的I/O性能提升。

Logo

技术共进,成长同行——讯飞AI开发者社区

更多推荐