实战篇-典型故障排查与性能问题诊断与优化

目录

1 概述

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

2.1 需要修复的场景

2.2 检查文件系统

2.3 修复过程

2.4 xfs常用命令

2.5 具体应用

2.6 最后方法

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

3.1 inode的定义

3.2 inode的组成

3.3 inode的作用

3.4 inode 耗尽的原因分析

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

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

3.7 实际案例分析

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

4.1 僵尸进程

4.2 分析

4.3 汇总

5 识别IOwait的十八种姿势

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

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

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

5.4 总结

6 使用SystemTap分析锁竞争

6.1 SystemTap简介

6.2 理解文件系统锁

6.3 编写 SystemTap 脚本

6.4 运行 SystemTap 脚本

6.5 分析输出

6.6 深入分析

7 文件系统性能优化

7.1 Disk相关参数

7.2 EXT3文件系统参数

7.3 mount参数


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_logprintprint the log of an XFS filesystem
xfs_mkfilecreate an XFS file
xfs_infoexpand an XFS filesystem
xfs_ncheckgenerate pathnames from i-numbers for XFS
xfs_rtcpXFS realtime copy command
xfs_freezesuspend access to an XFS filesystem
xfs_iodebug 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 等几个状态,它们分别是什么意思呢?

RRunning 或 Runnable 的缩写,表示进程在 CPU 的就绪队列中,正在运行或者正在等待运行
DDisk Sleep 的缩写,也就是不可中断状态睡眠(Uninterruptible Sleep),一般表示进程正在跟硬件交互,并且交互过程不允许被其他进程或中断打断
ZZombie 的缩写,如果你玩过“植物大战僵尸”这款游戏,应该知道它的意思。它表示僵尸进程,也就是进程实际上已经结束了,但是父进程还没有回收它的资源(比如进程的描述符、PID 等)
SInterruptible Sleep 的缩写,也就是可中断状态睡眠,表示进程因为等待某个事件而被系统挂起。当进程等待的事件发生时,它会被唤醒并进入 R 状态
IIdle 的缩写,也就是空闲状态,用在不可中断睡眠的内核线程上。前面说了,硬件交互导致的不可中断进程用 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性能提升。总的来说,主要可以从三个方面来做工作:

1Disk相关参数调优
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性能提升。

本文系统讲解了典型故障排查的一些方法与案例,以及性能问题的诊断与优化,本系列共4篇,链接如下:

基础篇-Linux存储体系核心概念之文件系统入门

进阶篇-系统机制与优化基础之VFS虚拟文件系统

高级篇-文件系统黑科技

实战篇-典型故障排查与性能问题诊断与优化

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值