当前位置:首页>Linux>生产级 Linux 磁盘 IO 调优:从原理到落地实战指南

生产级 Linux 磁盘 IO 调优:从原理到落地实战指南

  • 2026-07-02 19:18:09
生产级 Linux 磁盘 IO 调优:从原理到落地实战指南

背景与适用场景

磁盘IO性能是Linux服务器最常见的瓶颈之一。当服务器出现响应延迟增加、CPU的iowait占比居高不下、应用程序吞吐率下降时,磁盘IO往往是主要诱因。在生产环境中,以下场景经常需要关注和优化磁盘IO:

典型高IO场景:

  • 数据库服务器(MySQL、PostgreSQL、MongoDB)的数据盘和日志盘
  • 日志收集和分析服务器,大批量写入日志文件
  • 文件存储和对象存储服务,高并发读写小文件
  • 虚拟化和容器化环境的存储卷
  • 编译服务器和持续集成环境,大规模读写临时文件
  • 视频转码、图片处理等媒体 workloads

本文目标读者:初中级运维工程师,具备基本的Linux操作经验,熟悉常见的系统管理命令。希望通过本文能够:独立评估磁盘IO性能状态、定位IO瓶颈、掌握常用优化手段、在生产环境安全实施优化措施。

前置知识:

  • 基本的Linux命令操作能力
  • 了解CPU、内存、磁盘基本概念
  • 有过查看系统资源(top、free、df等)经验

第一章 磁盘IO核心概念

1.1 磁盘IO性能三要素

磁盘IO性能由三个核心指标衡量,它们相互关联但各自描述不同层面的性能特征:

IOPS(Input/Output Operations Per Second)IOPS表示每秒完成的IO操作次数,反映磁盘处理随机读写请求的能力。对于数据库等随机读写密集型 workload,IOPS是首要关注的指标。

吞吐量(Throughput)吞吐量表示每秒传输的数据量,通常以MB/s或GB/s为单位。它衡量的是顺序IO场景下的数据传输能力。大文件读写、视频流处理等场景主要关注吞吐量。

延迟(Latency)延迟指单个IO请求从发送到完成的时间。延迟直接影响应用程序的响应时间,特别是对延迟敏感的应用(如数据库事务)。

三者关系:

IOPS × 平均IO大小 = 吞吐量
延迟 × IOPS ≈ 一定程度的资源占用率(当IO并发度不高时)

例如,一个SSD的IOPS为50000,假设每次IO大小为4KB,则吞吐量为50000 × 4KB ≈ 195MB/s。

1.2 存储介质类型与特性

不同存储介质的IO特性差异巨大,理解这些差异是优化IO性能的基础。

机械硬盘(HDD)机械硬盘使用旋转磁盘和机械磁头。随机读写需要磁头寻道,延迟通常在5-15ms。7200RPM硬盘的IOPS通常在100-150之间,10000RPM高端盘可达200-300 IOPS。顺序读取吞吐量在100-200MB/s区间。

机械硬盘的IO延迟主要来自三个方面:旋转延迟(平均约4-5ms,取决于转速)、寻道延迟(平均3-8ms)、数据传输延迟。优化机械硬盘IO的核心思路是减少随机读写、尽量合并IO请求。

固态硬盘(SSD)SSD使用NAND Flash存储介质,无机械部件。随机读写延迟在0.1-0.5ms级别,IOPS可达50000以上,吞吐量在500MB-3GB/s区间(取决于接口和NAND类型)。

SATA SSD受SATA接口限制,实际吞吐量约500-600MB/s。NVMe SSD通过PCIe通道直连主机,吞吐量可达3GB/s以上。SSD的IO特性是:小IO请求延迟低,但大顺序写入可能触发写入放大效应。

NVMe SSD的特殊考虑NVMe SSD支持多队列(最多64000个命令队列),相比SATA SSD的单一命令队列,在高并发场景下性能优势明显。但NVMe SSD对内核版本和驱动有要求,老旧内核可能无法充分发挥NVMe性能。

存储类型选择建议:

数据库业务(随机IO为主)      → SSD或NVMe SSD,高IOPS优先
文件存储(顺序IO为主)        → 大容量HDD或SATA SSD,吞吐量优先
虚拟化/容器存储              → 至少SSD,建议NVMe SSD
日志收集(顺序写为主)        → 大容量HDD或SATA SSD

1.3 文件系统对IO的影响

文件系统是应用程序与存储设备之间的抽象层,不同文件系统在IO行为上有显著差异。

EXT4EXT4是RHEL/CentOS/Ubuntu等主流发行版的默认文件系统。EXT4的IO特性:

  • 最大文件系统容量:1EB,单文件最大16TB
  • 默认块大小:4KB
  • 支持延迟分配(delayed allocation),减少碎片但增加数据丢失风险
  • 日志模式:writeback、ordered、journal三种模式,默认ordered
  • 顺序读性能好,随机读性能一般

XFSXFS是RHEL 7/8/9默认文件系统,适合大文件和高IOPS场景。XFS的IO特性:

  • 最大文件系统容量:8EB,单文件最大8EB
  • 更好的并行IO支持,多线程IO性能优于EXT4
  • 元数据操作更高效,大目录遍历性能好
  • 默认日志模式:ordered
  • 随机写性能优于EXT4,但CPU开销略高

BtrfsBtrfs是下一代文件系统,支持写时复制、快照、压缩等高级特性。但生产环境使用需谨慎,成熟度不如EXT4和XFS。

tmpfs/ramfs内存文件系统,极低延迟,适合临时文件和缓存。但数据易失,需确保有足够内存且能接受数据丢失风险。

文件系统挂载选项对IO的影响:

# noatime:关闭访问时间更新,减少元数据写
# nodiratime:关闭目录访问时间更新
# barrier=1:启用磁盘写屏障,保证文件系统一致性(默认开启)
# nobarrier:关闭写屏障,提升写性能但有数据风险
# data=writeback:EXT4的writeback日志模式,写性能最好但最不安全
# data=ordered:折中模式,默认
# commit=60:延迟刷新元数据,默认5秒

# 高性能场景推荐挂载参数(注意数据安全)
mount -o noatime,nodiratime,nobarrier,data=writeback /dev/sdb1 /data

# 标准安全场景推荐
mount -o noatime,nodiratime /dev/sdb1 /data

文件系统IO特性对比:

特性
EXT4
XFS
最大单文件
16TB
8EB
大文件性能
很好
小文件性能
一般
较好
多线程IO
一般
很好
顺序读性能
随机写性能
一般
较好
元数据开销
中等
较低
碎片化影响
较敏感
不敏感

1.4 IO调度算法

Linux内核的IO调度器决定IO请求的发送顺序和合并策略。不同调度算法适合不同的IO模式。

调度算法类型:

CFQ(Completely Fair Queuing)基于进程公平队列的调度算法,力图给每个进程分配相等的IO带宽。在SSD上反而可能降低性能,因为CFQ的队列排序开销在快速设备上得不偿失。RHEL 6默认使用CFQ。

Deadline基于截止时间的调度算法,优先处理即将超时的请求,减少IO延迟抖动。对数据库等延迟敏感型应用友好。RHEL 6可选。

NOOP最简单的FIFO队列,只做相邻请求合并。适合SSD和存储阵列,因为这些设备本身有强大的调度能力,内核调度是冗余的。

MQ-DEADLINE和KYBER多队列版本的Deadline和KYBER调度器,专为NVMe SSD和高速存储设计,充分利用多核CPU和多队列硬件。RHEL 8/9默认使用。

BFQ(Budget Fair Queuing)基于权重的调度算法,适合桌面和交互式场景,可以保证低延迟。服务器场景一般不推荐。

查看和修改调度算法:

# 查看当前磁盘使用的调度算法
cat /sys/block/sda/queue/scheduler
# 输出示例:none [mq-deadline] kyber bfq 或 [deadline] cfq noop

# 查看具体一块磁盘的调度算法
cat /sys/block/sda/sda1/queue/scheduler  # 如果sda1是独立分区

# 临时修改调度算法(重启失效)
echo mq-deadline > /sys/block/sda/queue/scheduler

# 永久修改调度算法 - 通过udev规则
cat > /etc/udev/rules.d/60-io-scheduler.rules << 'EOF'
# 为SSD设置noop调度器
ACTION=="add|change", SUBSYSTEM=="block", ENV{ID_TYPE}=="disk", KERNEL=="sd[a-z]", ATTR{queue/rotational}=="0", ATTR{queue/scheduler}="noop"
# 为HDD设置deadline调度器
ACTION=="add|change", SUBSYSTEM=="block", ENV{ID_TYPE}=="disk", KERNEL=="sd[a-z]", ATTR{queue/rotational}=="1", ATTR{queue/scheduler}="deadline"
EOF

# 重新加载udev规则
udevadm control --reload-rules

调度算法选择建议:

SSD/NVMe存储          → noop或mq-deadline,减少调度开销
机械硬盘               → deadline,减少饥饿和延迟
数据库随机IO           → deadline,减少IO延迟
大文件顺序读写         → mq-deadline或noop
虚拟化/容器存储        → mq-deadline

第二章 磁盘IO性能评估工具

2.1 iostat - IO统计信息

iostat是分析磁盘IO最常用的工具,属于sysstat包。

安装:

# RHEL/CentOS
yum install sysstat -y

# Debian/Ubuntu
apt install sysstat -y

基本用法:

# 每秒刷新一次,显示CPU统计和设备IO
iostat 1

# 每2秒刷新一次,共显示5次
iostat 2 5

# 只显示设备IO统计,不显示CPU
iostat -d

# 显示指定设备
iostat -d sda sdb

# 显示扩展统计信息(包含更多指标)
iostat -x

# 显示KB为单位,配合-x更易读
iostat -xk

# 显示CPU和所有设备的扩展统计,每秒一次
iostat -xcz 1

典型输出解读:

iostat -xcz 1
Linux 5.4.0-164-generic (db-server)     05/11/2026     _x86_64_        (16 CPU)

avg-cpu:  %user   %nice %system %iowait %steal     %idle
          12.34    0.00    5.67    8.45    0.00    73.54

Device:   rrqm/s   wrqm/s     r/s     w/s    rkB/s    wkB/s  avgrq-sz avgqu-sz   await r_await w_await  svctm  %util
sda          0.00     2.33    1.23   45.67    15.32  1823.45    39.45     1.23   26.12   12.34   26.89   5.23  24.56

核心指标详解:

  • rrqm/s, wrqm/s:每秒合并的读/写请求数。合并说明调度器将多个相邻的小IO合并成一个大IO,减少请求次数。
  • r/s, w/s:每秒发送到设备的读/写请求数(不合并后)。
  • rkB/s, wkB/s:每秒读取/写入的KB数。
  • avgrq-sz:平均每个IO请求的大小(扇区数),可通过avgrq-sz×512字节换算。值越大说明IO越顺序,越小说明IO越随机。
  • avgqu-sz:平均队列深度,即设备驱动层的平均等待请求数。值越大说明IO压力越高。
  • await:平均IO响应时间(毫秒),包括在队列等待时间和实际服务时间。这是最直观的IO性能指标
  • r_await, w_await:分别针对读和写的平均响应时间。
  • svctm:平均服务时间(毫秒),设备处理IO的实际时间。注意:svctm在iostat -x中已标记为废弃,不应作为主要参考
  • %util:设备利用率,即设备忙碌时间占比。接近100%时说明设备成为瓶颈

性能问题判断标准:

# 判断设备是否饱和
# 当 %util > 80-90% 且 await 很高时,说明设备能力达到上限

# 判断是否存在IO延迟问题
# 当 await > 100ms(HDD)或 > 10ms(SSD)时,存在明显延迟

# 判断IO是否均衡
# 当 avgqu-sz 长期 > 4(单盘)或队列忽高忽低,说明IO模式有问题

# 判断IO大小是否合理
# 当 avgrq-sz 很小(如 < 16 sectors = 8KB),说明存在大量小IO

配合时间分析IO变化:

# 记录IO基线(正常时)
iostat -xcz 1 > /tmp/iostat_baseline.log &

# 问题发生时对比
# 正常时: await约20ms,%util约30%
# 问题时: await超过100ms,%util超过80%
# 对比发现设备成为瓶颈

2.2 iotop - 按进程查看IO使用

iotop可以显示每个进程的IO使用情况,是定位IO占用元凶的利器。

安装:

# RHEL/CentOS
yum install iotop -y

# Debian/Ubuntu
apt install iotop -y

基本用法:

# 交互式显示,按IO排序
iotop

# 非交互模式,显示一次
iotop -b

# 非交互,每秒刷新一次,共10次
iotop -b -n 10 -d 1

# 只显示有IO活动的进程
iotop -b -o

# 显示特定用户的进程
iotop -b -u mysql

# 显示累计IO,不显示速率
iotop -b -a

典型输出解读:

Total DISK READ:       1.23 M/s | Total DISK WRITE:      15.67 GB/s
Current DISK READ:       0.00 B/s | Current DISK WRITE:       1.23 M/s
TID  PRIO  USER     DISK READ  DISK WRITE  SWAPIN     IO    COMMAND
12345 be/4 mysql      15.32 K/s    0.00 B/s  0.00 %  0.23 % mysqld
12346 be/4 mysql       0.00 B/s   823.45 K/s  0.00 %  1.56 % mysqld
67890 be/3 root        0.00 B/s    12.34 K/s  0.00 %  0.01 % rsync

关键列说明:

  • TID:线程ID,top风格的TID
  • PRIO:优先级
  • DISK READ/WRITE:该进程的读写速率
  • IO:该进程占用的IO百分比(相对于总带宽)
  • COMMAND:进程名

实用技巧:

# 定位哪个进程导致高IO
iotop -b -n 1 -o | head -20

# 实时观察MySQL的IO行为
watch -n 1 'iotop -b -n 1 -u mysql'

# 查找大量小文件写的进程
iotop -b | awk '$4 ~ /^[0-9.]+[KMG]?$/ && $5 == "K/s" && $5+0 > 100 {print}'

2.3 pidstat - 按进程查看IO统计

pidstat是sysstat的一部分,可以按进程ID统计IO使用情况,比iotop更适合脚本化和长期监控。

基本用法:

# 显示每个进程的IO统计,每秒刷新
pidstat -d 1

# 只显示有IO活动的进程
pidstat -d 1 | grep -v "^[0-9]" | awk '$8 > 0 {print}'

# 查看特定进程的IO
pidstat -d -p 12345 1 10

# 显示扩展IO统计
pidstat -dx 1

# 输出格式:UID PID kB_rd/s kB_wr/s kB_ccwr/s iodelay COMMAND
# kB_rd/s: 每秒读取KB数
# kB_wr/s: 每秒写入KB数
# kB_ccwr/s: 每秒取消写入KB数(被进程取消的脏页)
# iodelay: IO等待的时钟周期数

定位高IO进程脚本:

#!/bin/bash
# 高IO进程检测脚本

echo"=== 高IO进程检测 ==="
echo"时间: $(date '+%Y-%m-%d %H:%M:%S')"
echo""

# 检测IO写入
echo"--- 磁盘写入TOP10 ---"
pidstat -d 1 5 | grep -v "^$" | awk '
NR>4 && $7 > 0 {
    split($7, a, "/");
    kb_wr = a[1]+0;
    if (kb_wr > 0) {
        print kb_wr " KB/s", $8, $9
    }
}'
 | sort -rn | head -10

echo""
echo"--- 磁盘读取TOP10 ---"
pidstat -d 1 5 | grep -v "^$" | awk '
NR>4 && $6 > 0 {
    split($6, a, "/");
    kb_rd = a[1]+0;
    if (kb_rd > 0) {
        print kb_rd " KB/s", $8, $9
    }
}'
 | sort -rn | head -10

2.4 top/atop - 查看IO等待

top命令的CPU部分包含iowait指标,可以快速判断是否存在IO瓶颈。

top查看iowait:

top -b -n 1
# 输出中%Cpu(s)行:
# 12.3 us,  5.6 sy,  0.0 ni, 73.5 id,  8.4 wa,  0.0 hi,  0.2 si,  0.0 st
# 这里的 8.4 wa 就是iowait,表示CPU等待IO完成的时间百分比

iowait的含义:

  • iowait高 ≠ 一定是磁盘IO问题,也可能是网络IO等待(但网络通常不计入iowait)
  • iowait高 + CPU idle低:说明CPU在等待IO,此时CPU不是瓶颈,IO是瓶颈
  • iowait高 + CPU idle高:说明CPU空闲但有IO在后台运行,这是正常的
  • iowait低 + CPU idle低:说明CPU在处理计算,瓶颈在CPU

atop更详细的视图:

# 安装atop
yum install atop -y  # 或 apt install atop

# 启动atop(默认每60秒采样一次)
atop

# 查看历史采样
atop -r /var/log/atop/atop_20230511

# atop界面的快捷键:
# g:总体视图
# d:磁盘视图
# m:内存视图
# c:CPU进程视图
# 按时间轴前进/后退:t / T

atop磁盘视图显示内容:

  • DISK列:每个磁盘的 busy%、read KB/s、write KB/s
  • TRANSFER列:IO传输速率
  • LAT列:平均延迟(ms)
  • DSK列:设备利用率

2.5 fio - 基准测试工具

fio是业界标准的存储基准测试工具,可以模拟各种IO模式,准确评估存储性能。

安装:

# RHEL/CentOS
yum install fio -y

# Debian/Ubuntu
apt install fio -y

常用测试场景:

# 1. 随机读测试(数据库读场景)
fio --name=randread --ioengine=libaio --iodepth=4 --rw=randread \
    --bs=4k --size=1G --numjobs=4 --runtime=60 --time_based=1 \
    --readonly --filename=/dev/sdb1

# 2. 随机写测试(数据库写场景)
fio --name=randwrite --ioengine=libaio --iodepth=4 --rw=randwrite \
    --bs=4k --size=1G --numjobs=4 --runtime=60 --time_based=1 \
    --filename=/dev/sdb1

# 3. 顺序读测试(大文件读取)
fio --name=seqread --ioengine=libaio --iodepth=16 --rw=read \
    --bs=128k --size=2G --numjobs=1 --runtime=60 --time_based=1 \
    --filename=/dev/sdb1

# 4. 顺序写测试
fio --name=seqwrite --ioengine=libaio --iodepth=16 --rw=write \
    --bs=128k --size=2G --numjobs=1 --runtime=60 --time_based=1 \
    --filename=/dev/sdb1

# 5. 混合读写测试(70%读30%写,模拟真实数据库)
fio --name=mixrw --ioengine=libaio --iodepth=4 --rw=randrw \
    --rwmixread=70 --bs=4k --size=1G --numjobs=4 --runtime=60 \
    --time_based=1 --filename=/dev/sdb1

# 6. 完整测试报告(使用预设配置文件)
fio --profile=library --filename=/dev/sdb1

关键参数说明:

# --ioengine: IO引擎
#   libaio: Linux原生异步IO,生产环境推荐
#   sync: 同步IO,最原始
#   posixaio: POSIX异步IO
#   libev: 事件驱动IO

# --iodepth: 队列深度,表示同时在途的IO请求数
#   4: 模拟单线程随机IO(如单次数据库事务)
#   16-32: 模拟多线程或数据库整体IO
#   64+: 模拟高并发场景

# --rw: 读写模式
#   read: 顺序读
#   write: 顺序写
#   randread: 随机读
#   randwrite: 随机写
#   randrw: 混合随机读写

# --bs: 块大小
#   4k: 数据库小IO随机读写
#   128k-1M: 大文件顺序IO

# --numjobs: 并发线程数
# --runtime: 测试持续时间(秒)
# --time_based: 如果文件读写完了,用时间而不是大小来控制测试时长

# --filename: 测试文件/设备
#   使用文件测试: --filename=/data/fio_testfile
#   使用裸设备测试: --filename=/dev/sdb1 (危险,会擦除数据!)

fio输出解读:

randread: (g=0): rw=randread, bs=4K-4K/4K-4K/4K-4K, ioengine=libaio, iodepth=4
...
Jobs: 4 (f=4): [R(4)][100.0%][r=15.2M/s,w=0K/s][r=3895,w=0] %uenc - ETA的省略
  write: IOPS=3895, BW=15.2MiB/s (15.9MB/s)
read: IOPS=3895, BW=15.2MiB/s (15.9MB/s)
read: IOPS=3895, BW=15.2MiB/s (15.9MB/s)
  write: IOPS=3895, BW=15.2MiB/s (15.9MB/s)

# 关键指标:
# IOPS: 每秒IO操作数
# BW: 吞吐量(MiB/s或MB/s)
# clat: completion latency,完成延迟
# slat: submission latency,提交延迟
# lat: 总体延迟

性能测试注意事项:

# 测试裸设备会擦除数据!生产环境禁止
# 正确做法:用文件测试
fio --name=test --size=10G --filename=/data/fio_test

# 测试完成后清理测试文件
rm -f /data/fio_test

# 建议在测试前记录基线性能
# 测试时确保系统IO相对空闲
# 多次测试取平均值以减少波动

2.6 hdparm - 读取磁盘硬件信息

hdparm可以查看磁盘硬件信息和做简单测速。

查看磁盘信息:

# 查看磁盘型号和基本参数
hdparm -I /dev/sda

# 读取磁盘缓存大小
hdparm -g /dev/sda

# 测试读取速度(直接从缓存读,不产生实际IO)
hdparm -Tt /dev/sda
# 输出示例:
# /dev/sda:
#  Timing cached reads:   5234 MB in  2.00 seconds = 2617.00 MB/sec
#  Timing buffered disk reads:  256 MB in  3.01 seconds =  85.05 MB/sec

hdparm注意事项:

  • hdparm主要针对SATA/IDE硬盘
  • NVMe设备部分功能不支持
  • 敏感参数修改(如-dmar、-X等)可能影响数据安全
  • 许多现代SSD不支持hdparm的某些高级功能

2.7 其他有用工具

df - 查看文件系统空间和inode使用:

# 查看文件系统使用情况
df -h

# 查看inode使用情况(大量小文件可能耗尽inode)
df -i

# 以inode显示
df -hi

# 查看磁盘挂载点和文件系统类型
df -Th

du - 估算目录空间使用:

# 查看当前目录大小
du -sh .

# 查看各子目录大小
du -sh */

# 显示文件大小排序
du -ah | sort -rh | head -20

# 查看大文件(100MB以上)
find / -type f -size +100M -exec ls -lh {} \;

lsblk - 查看块设备:

# 显示所有块设备及挂载点
lsblk

# 显示完整信息
lsblk -f

# 显示设备大小
lsblk -b

blkid - 查看设备UUID和文件系统类型:

blkid
# 输出:
# /dev/sda1: UUID="xxx" TYPE="xfs"
# /dev/sdb1: UUID="yyy" TYPE="ext4"

第三章 关键性能指标解读

3.1 %util - 设备利用率

%util的含义:设备利用率,表示设备在采样周期内处于忙碌状态的时间百分比。100%意味着设备全力运转,是判断设备是否饱和的直接指标。

判断方法:

# 单次采样不足以判断,持续观察
iostat -xcz 1

# 如果%util持续>80-90%,且其他指标(await)也明显升高
# 说明设备已经成为瓶颈

# 示例正常输出:
Device:  %util
sda      15.23   # 设备大部分时间空闲

# 示例饱和输出:
Device:  %util
sda      98.45   # 设备几乎满负荷

重要注意事项:

  • %util>100%是不可能的,看到100%只是采样精度问题
  • 即使%util只有30-50%,如果await很高,仍可能存在IO问题(队列瓶颈在驱动层)
  • SSD的%util高不一定代表性能差,要结合IOPS和吞吐量看
  • 多盘RAID环境下,单盘%util高可能不影响整体性能

3.2 await - 平均IO响应时间

await的含义:平均IO响应时间,从请求发送到完成的时间(毫秒),包括排队时间和实际服务时间。这是应用层面最关心的IO指标。

不同存储类型的await基线:

# 机械硬盘(HDD)基线:
# 正常负载: 5-15ms
# 轻度繁忙: 15-30ms
# 严重繁忙: >50ms(需要优化或扩容)

# SATA SSD基线:
# 正常负载: 0.1-1ms
# 轻度繁忙: 1-5ms
# 严重繁忙: >10ms

# NVMe SSD基线:
# 正常负载: 0.02-0.2ms
# 轻度繁忙: 0.2-1ms
# 严重繁忙: >2ms

# 网络存储(NFS/CIFS):
# 正常负载: 1-10ms
# 轻度繁忙: 10-30ms
# 严重繁忙: >50ms

await vs svctm:

  • await = 排队时间 + svctm
  • svctm是设备实际服务时间
  • 当设备空闲时,await≈svctm
  • 当设备繁忙时,await>svctm,差值就是排队时间
  • 不要单独看svctm判断性能,要看await的组成

3.3 avgqu-sz - 平均队列深度

avgqu-sz的含义:设备驱动的平均等待队列长度。在请求达到设备前,它们在内核的设备队列中等待。

队列深度的意义:

# 队列深度 = 并发在途IO数
# 当应用程序发的IO速度快于设备处理速度时,队列就会堆积

# 判断标准:
# avgqu-sz < 2:轻负载,设备能力强于IO需求
# avgqu-sz 2-4:正常负载
# avgqu-sz 4-8:较高负载,可能出现延迟
# avgqu-sz > 8:严重过载,IO延迟会显著增加

# 示例输出:
Device:  avgqu-sz   await  %util
sda          0.15    8.23   5.23   # 轻负载,正常
sdb         12.45   156.78  98.45  # 严重过载,需要优化

avgqu-sz突然升高的排查:

# 1. 查看是哪个进程导致
iotop -b -n 1 -o

# 2. 查看IO分布
pidstat -d 1

# 3. 查看IO类型分布
iostat -xcz 1

3.4 avgrq-sz - 平均IO大小

avgrq-sz的含义:平均每个IO请求的大小(以扇区为单位,1扇区=512字节)。这个指标反映IO的顺序性程度。

avgrq-sz解读:

# avgrq-sz = 8(约4KB):小IO,随机IO为主
# avgrq-sz = 64(约32KB):中等大小IO
# avgrq-sz = 256(约128KB):大IO,顺序IO为主

# 假设看到:
# avgrq-sz很小(如8-16),说明大量随机小IO
# avgrq-sz很大(如256+),说明IO比较顺序

# 数据库典型场景:
# InnoDB page size = 16KB,avgrq-sz约32-64
# 大量小查询可能导致avgrq-sz很小

如何通过avgrq-sz判断IO模式:

# 通过iostat计算
# 如果 rKB/s=1000, r/s=250,则avgrq-sz = 1000/250/2 = 2(约1KB)
# 说明大量小IO读

# 判断:
# avgrq-sz < 16(约8KB):小IO密集,随机读写
# avgrq-sz 16-64(约8-32KB):混合IO
# avgrq-sz > 64(约32KB+):大IO为主,顺序性强

3.5 读IO vs 写IO

r/s和w/s分别代表什么:

# 读IO(r/s):
#   - 来自应用程序的文件读取
#   - 数据库数据页读取
#   - 程序启动时的二进制读取
#   - 页面缓存回读

# 写IO(w/s):
#   - 应用程序的数据写入
#   - 日志写入
#   - 页面缓存回写(脏页刷新)
#   - 数据库WAL/redo日志写入

通过读写比例判断业务特征:

# 高读低写场景(读多写少):
# 数据库读 replica、静态内容服务、代码仓库
# 优化方向:增大缓存、优化读路径

# 低读高写场景(写多读少):
# 日志收集、时序数据库写入、消息队列持久化
# 优化方向:优化写路径、批量写入策略

# 读写均衡场景:
# OLTP数据库、文件存储服务
# 需要同时优化读写路径

3.6 常见IO瓶颈识别模式

模式1:设备利用率饱和

# 特征:
# - %util持续>90%
# - await明显升高
# - avgqu-sz增加

# 诊断命令:
iostat -xcz 1
# %util列持续在90%以上

# 原因:
# - 设备能力不足(需要换更快存储)
# - IO模式不匹配(随机IO打满设备能力)
# - 多个IO源竞争同一设备

模式2:队列堆积

# 特征:
# - avgqu-sz很高
# - await很高
# - %util可能不高(因为请求在排队)

# 诊断命令:
iostat -xcz 1
# avgqu-sz持续>8

# 原因:
# - 应用并发IO过多
# - 存储响应变慢(抖动)
# - 驱动层瓶颈

模式3:元数据瓶颈

# 特征:
# - %util不高,但延迟很高
# - 大量小IO(avgrq-sz很小)
# - iowait高

# 诊断命令:
iostat -xcz 1
# avgrq-sz很小(<8,约4KB以下)

# 原因:
# - 文件系统元数据操作频繁
# - 小文件读写
# - 大目录遍历/删除

# 解决方案:
# - 使用noatime减少stat调用
# - 优化目录结构
# - 使用tmpfs缓存

模式4:IO延迟抖动

# 特征:
# - await时高时低
# - %util波动大
# - 应用响应不稳定

# 诊断命令:
# 持续监控观察抖动
whiletruedo iostat -xcz 1 2>/dev/null | grep -A1 "Device:" | grep sda; sleep 1; done

# 原因:
# - 存储后端不稳定
# - 控制器缓存不足
# - 设备固件问题
# - 多个存储混合使用导致竞争

第四章 常见IO瓶颈排查思路

4.1 排查流程总览

┌─────────────────────────────────────────────────────────────┐
│                    IO瓶颈排查流程                            │
├─────────────────────────────────────────────────────────────┤
│  1. 发现现象:响应延迟、吞吐量下降、iowait高                │
│         ↓                                                  │
│  2. 初步判断:确认是IO问题还是CPU/网络问题                  │
│         ↓                                                  │
│  3. 定位瓶颈:哪个磁盘、哪个进程、什么类型的IO              │
│         ↓                                                  │
│  4. 分析根因:硬件限制、配置不当、架构问题                  │
│         ↓                                                  │
│  5. 制定方案:优化配置、调整架构、增加硬件                  │
│         ↓                                                  │
│  6. 实施验证:观察效果,确认问题解决                        │
│         ↓                                                  │
│  7. 长期方案:监控、预警、容量规划                          │
└─────────────────────────────────────────────────────────────┘

4.2 现象:响应延迟增加

第一步:确认是IO导致的延迟

# 查看CPU状态,确认是iowait高
top -b -n 1
# 观察wa列(iowait)

# 如果iowait > 20%,说明存在明显IO等待
# 如果idle接近0且iowait高,说明CPU在等IO
# 如果idle高但iowait也高,说明有后台IO但CPU没被占用

第二步:确认延迟来自磁盘IO

# 排除内存问题(swap导致IO)
free -h
# 查看swap used,如果swap used > 0,说明存在内存压力

# 查看swap in/out
vmstat 1
# si/so列显示swap活动,如果有大量swap IO,说明内存不足

# 查看进程IO
pidstat -d 1 5
# 观察是否有进程在大量读写

第三步:确认具体是哪种IO问题

# 查看磁盘使用情况
iostat -xcz 1

# 常见延迟原因判断:
# 1. 如果%util高 + await高 → 设备能力达到上限
# 2. 如果avgqu-sz高 + await高 → 请求堆积
# 3. 如果avgrq-sz很小 → 小IO太多
# 4. 如果w/s远大于r/s → 写IO过多

4.3 现象:iowait持续高

排查步骤:

# 步骤1:确认iowait来源
top -b -n 1
# 如果%Cpu的wa列持续>15%,确认是IO问题

# 步骤2:定位是哪个磁盘
iostat -xcz 1
# 查看各磁盘的%util、await

# 步骤3:定位是哪个进程
iotop -b -n 1 -o
# 找出IO占用最高的进程

# 步骤4:分析IO类型
pidstat -d -p <PID> 1
# 观察读写比例和IO大小

常见iowait高原因:

# 原因1:大量小文件读写
# 现象:avgrq-sz很小(<8,约4KB),w/s或r/s很高
# 解决:优化应用IO模式、使用缓存、合并小文件

# 原因2:大文件顺序读写
# 现象:avgrq-sz很大(>128),吞吐量达到上限
# 解决:确认设备能力是否满足,考虑升级存储

# 原因3:swap频繁换入换出
# 现象:si/so列有大量活动
# 解决:增加内存、优化应用内存使用、减少swap使用

# 原因4:日志大量写入
# 现象:w/s很高
# 解决:优化日志策略、异步日志、分散日志写入

# 原因5:数据库WAL写入
# 现象:w/s高且IO大小固定(如16KB)
# 解决:优化WAL配置、使用电池备份写缓存

4.4 现象:吞吐量下降

排查步骤:

# 步骤1:确认吞吐量确实下降
# 记录当前基线
iostat -xcz 1
# 对比正常状态的rkB/s和wkB/s

# 步骤2:检查是否有硬件/驱动问题
dmesg | grep -i "error\|fail\|timeout"
# 查看系统日志是否有存储错误

# 步骤3:检查RAID/存储控制器状态
# 如果是RAID卡:
 MegaCli -PDList -aAll | grep -E "Firmware state|Segments"
# 查看磁盘状态是否正常

# 步骤4:检查是否有坏道/故障块
smartctl -a /dev/sda
# 检查SMART信息

4.5 排查案例:MySQL数据库IO高

完整排查流程:

# 1. 发现问题:数据库响应慢
# 应用层报错:SQL执行时间超过阈值

# 2. 初步判断:查看CPU和IO状态
top -b -n 1
# 发现%Cpu的wa列达到45%,iowait非常高

# 3. 定位瓶颈磁盘
iostat -xcz 1
# 输出显示sdb(数据盘)的%util达到95%,await=120ms
# sda(系统盘)正常

# 4. 定位元凶进程
iotop -b -n 5 | grep -v "Total" | sort -k10 -rn | head -10
# 发现mysqld进程占用了90%以上的IO

# 5. 分析MySQL IO特征
pidstat -d -p $(pgrep -x mysqld) 1 10
# 显示写IO为主,每秒写入量约50MB

# 6. 检查MySQL相关指标
mysql -e "SHOW ENGINE INNODB STATUS\G" | grep -A5 "LOG"
# 查看redo log写入情况

mysql -e "SHOW GLOBAL STATUS LIKE 'Innodb_os_log%';"
# 查看日志写IO

mysql -e "SHOW GLOBAL STATUS LIKE 'Innodb_page_size';"
# 确认page size

# 7. 检查慢查询
mysql -e "SHOW FULL PROCESSLIST;"
# 发现大量慢查询在等待IO

mysql -e "SELECT * FROM mysql.slow_log ORDER BY start_time DESC LIMIT 10;"
# 查看慢查询日志

# 8. 根因分析
# - 存在大量随机小查询,导致频繁数据页读取
# - 合并写导致日志写入突增
# - innodb_flush_log_at_trx_commit=1 导致每次事务都刷日志

# 9. 优化方案(见后续章节)

4.6 排查脚本模板

IO问题快速诊断脚本:

#!/bin/bash
# io_diagnose.sh - IO问题快速诊断脚本
# 用途:快速收集IO问题诊断信息

OUTPUT_DIR="/tmp/io_diagnose_$(date +%Y%m%d_%H%M%S)"
mkdir -p "$OUTPUT_DIR"

echo"=== IO问题诊断 ==="
echo"输出目录: $OUTPUT_DIR"
echo"开始时间: $(date)"

# 1. 系统基本信息
echo"--- 系统信息 ---" > "$OUTPUT_DIR/01_system_info.txt"
uname -a >> "$OUTPUT_DIR/01_system_info.txt"
cat /etc/redhat-release >> "$OUTPUT_DIR/01_system_info.txt" 2>/dev/null
cat /etc/os-release >> "$OUTPUT_DIR/01_system_info.txt" 2>/dev/null

# 2. 磁盘分区和挂载
echo"--- 磁盘分区 ---" > "$OUTPUT_DIR/02_disks.txt"
lsblk >> "$OUTPUT_DIR/02_disks.txt"
echo"" >> "$OUTPUT_DIR/02_disks.txt"
df -Th >> "$OUTPUT_DIR/02_disks.txt"

# 3. 存储设备信息
echo"--- 存储设备信息 ---" >> "$OUTPUT_DIR/02_disks.txt"
for disk in $(lsblk -ndo NAME); do
if [ -e "/sys/block/$disk/queue/scheduler" ]; then
echo"=== $disk ===" >> "$OUTPUT_DIR/02_disks.txt"
        cat "/sys/block/$disk/queue/scheduler" >> "$OUTPUT_DIR/02_disks.txt"
        cat "/sys/block/$disk/queue/read_ahead_kb" >> "$OUTPUT_DIR/02_disks.txt"
echo"" >> "$OUTPUT_DIR/02_disks.txt"
fi
done

# 4. CPU和内存状态
echo"--- CPU状态 ---" > "$OUTPUT_DIR/03_cpu_mem.txt"
top -b -n 1 >> "$OUTPUT_DIR/03_cpu_mem.txt"
echo"" >> "$OUTPUT_DIR/03_cpu_mem.txt"
echo"--- 内存状态 ---" >> "$OUTPUT_DIR/03_cpu_mem.txt"
free -h >> "$OUTPUT_DIR/03_cpu_mem.txt"

# 5. IO统计(采样30秒)
echo"--- IO统计(30秒采样)---" > "$OUTPUT_DIR/04_io_stats.txt"
iostat -xcz 1 30 >> "$OUTPUT_DIR/04_io_stats.txt"

# 6. 高IO进程(采样30秒)
echo"--- 高IO进程(30秒采样)---" > "$OUTPUT_DIR/05_top_io_processes.txt"
pidstat -d 1 30 | awk '$8 > 0 || $9 > 0' >> "$OUTPUT_DIR/05_top_io_processes.txt"

# 7. dmesg存储错误
echo"--- 内核存储错误 ---" > "$OUTPUT_DIR/06_dmesg_errors.txt"
dmesg | grep -i "error\|fail\|timeout\|玉" >> "$OUTPUT_DIR/06_dmesg_errors.txt" || echo"未发现存储相关错误"

# 8. SMART信息(如有)
echo"--- SMART信息 ---" > "$OUTPUT_DIR/07_smart.txt"
for disk in $(lsblk -ndo NAME | grep -E '^sd[a-z]$'); do
ifwhich smartctl >/dev/null 2>&1; then
echo"=== $disk ===" >> "$OUTPUT_DIR/07_smart.txt"
        smartctl -H -i /dev/$disk >> "$OUTPUT_DIR/07_smart.txt" 2>&1
echo"" >> "$OUTPUT_DIR/07_smart.txt"
fi
done

echo"诊断完成,输出在: $OUTPUT_DIR"
echo"建议查看顺序:"
echo"1. 03_cpu_mem.txt - 确认iowait"
echo"2. 04_io_stats.txt - 确认哪个磁盘%util高"
echo"3. 05_top_io_processes.txt - 确认哪个进程IO高"
echo"4. 06_dmesg_errors.txt - 检查硬件错误"

第五章 IO性能优化实战

5.1 文件系统层面优化

选择合适的文件系统

根据业务场景选择文件系统:

# 高性能数据库场景
# 推荐XFS,适合大并发随机IO,元数据操作高效
mkfs.xfs -f /dev/sdb1

# 大文件存储场景
# XFS或EXT4都可以,XFS在大文件方面略有优势
mkfs.ext4 -F /dev/sdb1

# 需要高级特性(快照、压缩)
# 考虑Btrfs(但生产环境慎用)
mkfs.btrfs /dev/sdb1

合理的挂载选项

# 高性能场景(数据可丢失或已有备份)
# 关闭访问时间更新、关闭barrier、使用writeback模式
mount -o noatime,nodiratime,nobarrier,data=writeback /dev/sdb1 /data

# 标准安全场景
mount -o noatime,nodiratime /dev/sdb1 /data

# 查看当前挂载选项
mount | grep /data
# 或
cat /proc/mounts | grep /data

挂载选项详解:

选项
作用
性能影响
安全影响
noatime
不更新文件访问时间
减少元数据写
轻微(stat仍更新ctime)
nodiratime
不更新目录访问时间
减少元数据写
轻微
barrier=1
启用写屏障
降低写性能
保证数据一致性
nobarrier
关闭写屏障
提升写性能
断电可能丢数据
data=writeback
EXT4写回模式
最高写性能
可能丢数据
data=ordered
EXT4有序模式
折中
折中
commit=60
元数据刷新间隔
减少刷新次数
增加数据丢失窗口

文件系统检查和修复

# 检查文件系统(必须先卸载)
umount /data
fsck.ext4 -f /dev/sdb1

# XFS检查(XFS通常不需要定期检查)
xfs_repair /dev/sdb1

# 查看文件系统详细信息
dumpe2fs -h /dev/sdb1  # EXT4
xfs_info /dev/sdb1      # XFS

文件描述符和inode优化

# 查看当前限制
ulimit -n

# 临时修改(当前会话)
ulimit -n 65535

# 永久修改 - /etc/security/limits.conf
cat >> /etc/security/limits.conf << 'EOF'
*    soft    nofile    65535
*    hard    nofile    65535
*    soft    nproc     65535
*    hard    nproc     65535
EOF

# 查看inode使用情况
df -i
# 如果inode快耗尽,需要重新格式化或使用更多分区

5.2 内核参数优化

脏页回写参数

# 查看当前脏页配置
cat /proc/sys/vm/dirty_ratio          # 触发强制回写的内存比例
cat /proc/sys/vm/dirty_background_ratio # 后台回写的内存比例
cat /proc/sys/vm/dirty_expire_centisecs # 脏页过期时间(1/100秒)
cat /proc/sys/vm/dirty_writeback_centisecs # 回写间隔

# 默认值通常是:
# dirty_ratio = 20
# dirty_background_ratio = 10
# dirty_expire_centisecs = 3000(30秒)
# dirty_writeback_centisecs = 500(5秒)

脏页参数调整建议:

# 高IO压力场景(如数据库)
# 增大dirty_ratio,允许更多脏页积累再回写
# 减少回写频率,但增加数据丢失风险

cat >> /etc/sysctl.conf << 'EOF'
# 脏页参数优化
vm.dirty_ratio = 40
vm.dirty_background_ratio = 10
vm.dirty_expire_centisecs = 3000
vm.dirty_writeback_centisecs = 500

# 其他IO相关参数
vm.swappiness = 10           # 降低swap倾向
vm.zone_reclaim_mode = 0    # 禁用zone reclaim,减少本地分配失败
EOF

# 应用配置
sysctl -p

IO调度参数

# 查看当前调度器
cat /sys/block/sda/queue/scheduler

# 为SSD设置noop调度器(通过udev规则永久生效)
cat > /etc/udev/rules.d/60-io-scheduler.rules << 'EOF'
# SSD使用noop调度器
ACTION=="add|change", SUBSYSTEM=="block", KERNEL=="sd[a-z]", ATTR{queue/rotational}=="0", ATTR{queue/scheduler}="noop"
# HDD使用deadline调度器
ACTION=="add|change", SUBSYSTEM=="block", KERNEL=="sd[a-z]", ATTR{queue/rotational}=="1", ATTR{queue/scheduler}="deadline"
EOF

# 重新加载规则
udevadm control --reload-rules

# 验证生效
cat /sys/block/sda/queue/scheduler

预读参数

# 查看当前预读值(单位KB)
cat /sys/block/sda/queue/read_ahead_kb

# 临时修改
echo 4096 > /sys/block/sda/queue/read_ahead_kb

# 永久修改 - /etc/rc.d/rc.local
cat >> /etc/rc.d/rc.local << 'EOF'
# 设置预读值
blockdev --setra 4096 /dev/sda
blockdev --setra 4096 /dev/sdb
EOF
chmod +x /etc/rc.d/rc.local

# 预读值建议:
# 数据库随机读场景:128-512KB(减小,因为随机读不需要大预读)
# 大文件顺序读:1-4MB(增大)
# 混合场景:512KB-1MB

IO队列深度

# 查看队列深度
cat /sys/block/sda/queue/nr_requests

# 默认值128,对于高性能存储可以增大
# 注意:过大的队列可能导致延迟增加

# 临时修改
echo 256 > /sys/block/sda/queue/nr_requests

# 永久修改 - /etc/sysctl.conf
cat >> /etc/sysctl.conf << 'EOF'
# IO队列深度
kernel.sched_nr_migrate = 32
fs.nr_open = 65535
EOF

# 注意:nr_requests需要在启动脚本中设置,因为它是每设备的

5.3 应用程序层面优化

应用层IO模式优化原则

  1. 批量操作:合并多次小IO为一次大IO
  2. 异步IO:非关键IO异步处理,不阻塞主流程
  3. 缓存:使用内存缓存减少磁盘IO
  4. 预取:对可预测的读操作提前预取
  5. 顺序写:日志等写操作尽量顺序

数据库IO优化(MySQL InnoDB)

# MySQL配置文件 /etc/my.cnf 或 /etc/mysql/my.cnf

[mysqld]
# InnoDB数据文件和日志文件
innodb_data_file_path = ibdata1:1G;ibdata2:1G:autoextend
innodb_log_file_size = 1G
innodb_log_files_in_group = 3
innodb_flush_log_at_trx_commit = 1  # 1=最安全,2=折中,0=最快

# Buffer Pool配置
innodb_buffer_pool_size = 12G  # 通常设置为可用内存的60-80%
innodb_buffer_pool_instances = 4  # 多实例减少锁竞争

# IO相关参数
innodb_flush_method = O_DIRECT  # 绕过页面缓存,直接IO
innodb_io_capacity = 2000        # SSD建议2000-10000
innodb_io_capacity_max = 4000    # SSD建议4000-20000
innodb_read_io_threads = 8
innodb_write_io_threads = 8

# 临时表和排序优化
tmp_table_size = 256M
max_heap_table_size = 256M
sort_buffer_size = 4M
join_buffer_size = 4M

# Redo log优化
innodb_log_buffer_size = 64M

# 双一原则解释:
# innodb_flush_log_at_trx_commit=1 + sync_binlog=1
# 每次事务提交都刷新redo log和binlog
# 最安全但IO最多
# 如果可以容忍少量事务丢失,可设为2

Redis IO优化

# Redis配置文件 /etc/redis/redis.conf

# 持久化策略选择
# 如果不需要RDB和AOF:
appendonly no
save ""

# 如果需要AOF持久化:
appendonly yes
appendfilename "appendonly.aof"

# AOF刷盘策略
# everysec:每秒刷盘,最多丢失1秒数据(推荐)
appendfsync everysec

# no:不主动刷盘,由系统决定(最快但丢数据多)
# always:每次写都刷盘(最安全但最慢)

# AOF重写优化
no-appendfsync-on-rewrite yes  # 重写期间暂停appendfsync

# 内存策略
maxmemory 8gb
maxmemory-policy allkeys-lru

# 如果用RDB持久化:
save 900 1    # 900秒内至少1个key变化则保存
save 300 10   # 300秒内至少10个key变化则保存
save 60 10000 # 60秒内至少10000个key变化则保存

5.4 存储配置层面优化

RAID级别选择

RAID级别
读性能
写性能
冗余
磁盘利用率
典型场景
RAID0
100%
临时数据、高性能不需要冗余
RAID1
略差
50%
系统盘、启动盘
RAID5
略差
(n-1)/n
一般业务数据
RAID6
较差
(n-2)/n
需要高可靠的数据
RAID10
很好
很好
50%
数据库、高IO场景

RAID卡缓存配置

# 查看RAID卡型号
lspci | grep -i raid

# 使用MegaCli查看RAID配置(如果使用LSI卡)
MegaCli -CfgDsply -aALL | grep -E "RAID Level|Size|Cache" | head -20

# 启用RAID卡缓存(需要电池或超级电容)
MegaCli -LDSetProp -CachedBadBBU -Lall -aAll   # 启用缓存
MegaCli -LDSetProp -Direct -Lall -aAll         # 直通模式(关闭缓存)

# 查看RAID卡缓存设置
MegaCli -LDGetProp -Cache -Lall -aAll

# 注意:
# 如果没有电池保护写缓存,关闭写缓存以防断电丢失数据
# WriteBack模式:性能好但需要电池保护
# WriteThrough模式:性能差但安全

LVM缓存配置

# 使用LVM SSD缓存加速HDD
# 假设:
# /dev/sda1 - SSD,作为缓存设备
# /dev/sdb1 - HDD,作为慢速数据设备

# 1. 创建PV
pvcreate /dev/sda1
pvcreate /dev/sdb1

# 2. 创建VG
vgcreate vg_data /dev/sdb1
vgextend vg_data /dev/sda1

# 3. 创建缓存池
lvcreate --type cache-pool -l 100%FREE -n cache_pool vg_data /dev/sda1

# 4. 将缓存池关联到逻辑卷
lvconvert --cache --cachemode writethrough vg_data/lv_data --cachepool vg_data/cache_pool

# 5. 查看缓存状态
lvs -o lv_name,cache_read_hits,cache_read_misses,cache_mode vg_data

# cachemode选项:
# writethrough:数据同时写入SSD和HDD,安全
# writeback:数据先写入SSD,后台写入HDD,性能更好但有风险

5.5 常见IO问题修复示例

场景1:大量小文件导致IO高

# 问题:大量小文件读写导致%util高但吞吐量低
# 现象:avgrq-sz很小(约4KB),iowait高

# 解决方案1:合并小文件
# 使用cat合并小日志文件
cat /var/log/app/*.log > /var/log/app/merged_$(date +%Y%m%d).log

# 解决方案2:使用tmpfs缓存
# 在内存中创建tmpfs挂载点存储临时文件
mount -t tmpfs -o size=2G tmpfs /tmp/app_cache

# 解决方案3:优化应用IO模式
# 如果是代码问题,引导开发修改:
# - 批量写入而不是单条写入
# - 使用缓冲IO
# - 异步写日志

# 解决方案4:使用更合适的文件系统
# XFS对小文件支持更好
# 或考虑在SSD上运行

场景2:日志写入阻塞

# 问题:应用日志写入导致IO延迟
# 现象:w/s很高,IO延迟增加

# 解决方案1:日志异步化
# 修改应用配置,将日志输出到内存文件系统
mount -t tmpfs -o size=1G tmpfs /var/log/app_async
# 应用写入/var/log/app_async/
# 另一进程定期同步到磁盘

# 解决方案2:使用rsyslog远程日志
# 编辑 /etc/rsyslog.conf
*.* @@remote-log-server:514
# 日志通过网络发送到远程日志服务器

# 解决方案3:日志轮转优化
# /etc/logrotate.conf
daily           # 每天轮转
rotate 7        # 保留7天
compress        # 压缩旧日志
delaycompress   # 延迟压缩(上一次轮转的)
missingok        # 忽略丢失文件
notifempty       # 空文件不轮转
sharedscripts   # 所有日志轮转后只执行一次脚本
postrotate
    /bin/kill -HUP $(cat /var/run/rsyslogd.pid 2>/dev/null) 2>/dev/null || true
endscript

# 解决方案4:使用noatime减少stat调用
# 重新挂载
mount -o remount,noatime,nodiratime /var/log

场景3:数据库IO延迟抖动

# 问题:数据库IO延迟时高时低,不稳定
# 现象:await波动大,平均值高

# 诊断:查看是否有IO竞争
iostat -xcz 1 > /tmp/iostat.log &

# 同时观察其他进程
pidstat -d 1 &

# 解决方案1:隔离数据库IO
# 如果有多个磁盘,将数据目录、日志、临时目录分开
# MySQL示例:
[mysqld]
datadir=/data/mysql/data
innodb_log_group_home_dir=/data/mysql/redolog
tmpdir=/tmp/mysql

# 解决方案2:绑定磁盘IO到特定磁盘
# 使用cgroup限制其他进程的IO
# 安装blkio cgroup
yum install libcgroup -y
service cgconfig start

# 创建cgroup
cat > /etc/cgconfig.conf << 'EOF'
group db {
    blkio {
        blkio.throttle.read_bps_device="8:1 100M";
        blkio.throttle.write_bps_device="8:1 100M";
    }
}
EOF

# 将MySQL加入cgroup
# 需要在启动脚本中添加

# 解决方案3:使用IO优先级
# ionice命令设置进程IO调度优先级
# -c 1: real time(最高)
# -c 2: best effort(默认)
# -c 3: idle(最低)

# MySQL使用idle优先级,不影响其他进程
ionice -c 3 -p $(pgrep -x mysqld)

# 或使用rt(real time)保证数据库IO优先
ionice -c 1 -n 0 -p $(pgrep -x mysqld)

# 解决方案4:固定IO调度器
# 通过udev规则确保所有SSD使用noop
cat > /etc/udev/rules.d/60-ssd-scheduler.rules << 'EOF'
ACTION=="add|change", SUBSYSTEM=="block", ATTR{queue/rotational}=="0", ATTR{queue/scheduler}="noop"
EOF

第六章 监控与预警

6.1 关键监控指标

操作系统层面

# 需要监控的关键指标:

# 1. 磁盘利用率
# - %util > 80% 持续5分钟 → 告警
# - %util > 95% 持续1分钟 → 严重告警

# 2. IO响应时间
# - await > 100ms(HDD)或 > 10ms(SSD) → 告警
# - await > 500ms → 严重告警

# 3. IO队列深度
# - avgqu-sz > 4 持续5分钟 → 告警
# - avgqu-sz > 8 → 严重告警

# 4. IOPS和吞吐量
# - 吞吐量接近设备能力上限 → 告警
# - 吞吐量突然下降50%以上 → 严重告警

# 5. 磁盘使用率
# - 使用率 > 80% → 告警
# - 使用率 > 95% → 严重告警

# 6. inode使用率
# - inode使用率 > 80% → 告警
# - df -i 查看

数据库层面(MySQL)

# 监控SQL:
# 1. Innodb_buffer_pool_wait_free
# - 正常值接近0,如果持续增长说明buffer pool太小

# 2. Innodb_log_waits
# - redo log空间不足时需要等待
# - 值持续增长说明需要增大redo log

# 3. Slow_queries
# - 慢查询数量
# - 超过阈值告警

# 4. Questions / Queries
# - QPS监控
# - 异常下降需要关注

# 监控脚本示例
mysql -e "
SELECT
    VARIABLE_NAME,
    VARIABLE_VALUE,
    @@GLOBAL.${VARIABLE_NAME} AS GLOBAL_VALUE
FROM information_schema.GLOBAL_STATUS
WHERE VARIABLE_NAME IN (
    'Innodb_buffer_pool_wait_free',
    'Innodb_log_waits',
    'Slow_queries',
    'Questions',
    'Innodb_rows_read',
    'Innodb_rows_write'
)
ORDER BY VARIABLE_NAME;
"

6.2 Prometheus + node_exporter 监控方案

安装node_exporter

# 下载node_exporter
wget https://github.com/prometheus/node_exporter/releases/download/v1.6.1/node_exporter-1.6.1.linux-amd64.tar.gz
tar xzf node_exporter-1.6.1.linux-amd64.tar.gz
cd node_exporter-1.6.1.linux-amd64

# 启动node_exporter
./node_exporter &
# 默认监听在9100端口

# 测试指标输出
curl http://localhost:9100/metrics | grep node_disk

关键磁盘IO指标(Prometheus)

# 磁盘利用率
100 * (node_disk_io_time_seconds_total{job="node"} / (interval_avg * node_disk_io_time_weighted_seconds_total{job="node"}))

# 或者使用rate计算
rate(node_disk_io_time_seconds_total[5m]) * 100

# IO延迟
rate(node_disk_read_time_seconds_total[5m]) / rate(node_disk_reads_completed_total[5m])
rate(node_disk_write_time_seconds_total[5m]) / rate(node_disk_writes_completed_total[5m])

# 吞吐量
rate(node_disk_read_bytes_total[5m])
rate(node_disk_written_bytes_total[5m])

# IOPS
rate(node_disk_reads_completed_total[5m])
rate(node_disk_writes_completed_total[5m])

# 队列深度(如果系统支持)
node_disk_io_queue_depth_sum / node_disk_io_queue_depth_count

Grafana仪表盘配置

{
"dashboard": {
"title""Disk IO监控",
"panels": [
      {
"title""磁盘利用率 %util",
"targets": [
          {
"expr""rate(node_disk_io_time_seconds_total{device=\"sda\"}[5m]) * 100",
"legendFormat""%util - {{device}}"
          }
        ]
      },
      {
"title""IO延迟 (ms)",
"targets": [
          {
"expr""rate(node_disk_read_time_seconds_total{device=\"sda\"}[5m]) / rate(node_disk_reads_completed_total{device=\"sda\"}[5m]) * 1000",
"legendFormat""read await - {{device}}"
          },
          {
"expr""rate(node_disk_write_time_seconds_total{device=\"sda\"}[5m]) / rate(node_disk_writes_completed_total{device=\"sda\"}[5m]) * 1000",
"legendFormat""write await - {{device}}"
          }
        ]
      },
      {
"title""IO吞吐量 (MB/s)",
"targets": [
          {
"expr""rate(node_disk_read_bytes_total{device=\"sda\"}[5m]) / 1024 / 1024",
"legendFormat""read - {{device}}"
          },
          {
"expr""rate(node_disk_written_bytes_total{device=\"sda\"}[5m]) / 1024 / 1024",
"legendFormat""write - {{device}}"
          }
        ]
      }
    ]
  }
}

6.3 告警规则配置

AlertManager告警规则(Prometheus格式)

# /etc/prometheus/rules/disk_io_alerts.yml

groups:
-name:disk_io_alerts
rules:
# 磁盘利用率过高
-alert:DiskIOHighUtilization
expr:rate(node_disk_io_time_seconds_total[5m])*100>80
for:5m
labels:
severity:warning
annotations:
summary:"磁盘IO利用率过高"
description:"磁盘 {{ $labels.device }} 利用率超过80%,当前值: {{ $value }}%"

-alert:DiskIOCriticalUtilization
expr:rate(node_disk_io_time_seconds_total[5m])*100>95
for:1m
labels:
severity:critical
annotations:
summary:"磁盘IO利用率严重"
description:"磁盘 {{ $labels.device }} 利用率超过95%,当前值: {{ $value }}%"

# IO延迟过高
-alert:DiskIOHighLatency
expr:|
          (
            rate(node_disk_read_time_seconds_total[5m]) /
            rate(node_disk_reads_completed_total[5m])
          ) * 1000 > 50
for:5m
labels:
severity:warning
annotations:
summary:"磁盘IO延迟过高"
description:"磁盘 {{ $labels.device }} 读延迟超过50ms,当前值: {{ $value }}ms"

# 磁盘空间不足
-alert:DiskSpaceLow
expr:(node_filesystem_avail_bytes/node_filesystem_size_bytes)<0.2
for:10m
labels:
severity:warning
annotations:
summary:"磁盘空间不足"
description:"挂载点 {{ $labels.mountpoint }} 剩余空间不足20%,当前: {{ $value | humanizePercentage }}"

# inode空间不足
-alert:DiskInodesLow
expr:(node_filesystem_files_free/node_filesystem_files)<0.1
for:10m
labels:
severity:warning
annotations:
summary:"inode空间不足"
description:"挂载点 {{ $labels.mountpoint }} inode剩余不足10%"

告警阈值调整建议

# 不同存储类型需要不同的阈值:

# 机械硬盘(HDD)
# %util > 70% 持续5分钟 → 告警
# await > 30ms → 告警

# SATA SSD
# %util > 80% 持续5分钟 → 告警
# await > 5ms → 告警

# NVMe SSD
# %util > 90% 持续5分钟 → 告警(NVMe可以更高利用率)
# await > 2ms → 告警

# 阈值需要结合业务基线调整
# 如果正常时%util就是60%,应该相应提高告警阈值

6.4 长期性能趋势分析

建立性能基线

# 正常业务时采集基线数据
mkdir -p /var/log/io_baseline

# 定期采集iostat数据
whiletruedo
    timestamp=$(date '+%Y-%m-%d %H:%M:%S')
    iostat -xcz 1 5 >> "/var/log/io_baseline/iostat_$(date +%Y%m%d).log"
    sleep 300  # 每5分钟采集一次
done &

# 定期采集sar数据(需要sysstat)
# 确保sar数据收集开启
# RHEL/CentOS: 修改 /etc/default/sysstat 设置 ENABLED="true"
# 重启服务: service sysstat restart

# 查看历史IO数据
sar -d -p 1 5    # 设备IO历史
sar -b 1 5       # 缓冲区和IO传输统计

性能趋势分析

# 使用awk分析历史iostat数据
# 提取每日平均%util
awk '/^Device:/ {device=$2} /sda/ {sum+=$NF; cnt++} END {print "Avg util:", sum/cnt "%"}' /var/log/io_baseline/iostat_*.log

# 分析峰值时间分布
awk '/^Device:/ {device=$2} /sda/ && $NF>80 {print $1, $2, $NF}' /var/log/io_baseline/iostat_*.log

# 生成性能报告
cat > /usr/local/bin/io_report.sh << 'EOF'
#!/bin/bash
# IO性能周报生成脚本

REPORT_DIR="/var/log/io_reports"
mkdir -p "$REPORT_DIR"

DATE=$(date +%Y%m%d)
REPORT="$REPORT_DIR/io_report_${DATE}.txt"

echo"=== IO性能周报 ===" > "$REPORT"
echo"生成时间: $(date)" >> "$REPORT"
echo"" >> "$REPORT"

# 分析本周数据
for day in {1..7}; do
    DAY=$(date -d "$day days ago" +%Y%m%d)
    FILE="/var/log/io_baseline/iostat_${DAY}.log"

if [ -f "$FILE" ]; then
echo"--- $DAY ---" >> "$REPORT"
echo"平均%util: $(awk '/sda/ {sum+=$NF; cnt++} END {print (cnt?sum/cnt:"N/A")}' $FILE)" >> "$REPORT"
echo"峰值%util: $(awk '/sda/ {if($NF>max) max=$NF} END {print max}' $FILE)" >> "$REPORT"
echo"" >> "$REPORT"
fi
done

echo"报告生成: $REPORT"
EOF

chmod +x /usr/local/bin/io_report.sh

第七章 风险控制与回滚

7.1 生产环境操作风险评估

操作风险分级

# 风险等级1:低风险,可直接执行
# - 只读操作和查询
# - 监控和诊断
# - 配置文件查看
# 示例:iostat查看、pidstat监控、查看日志

# 风险等级2:中风险,建议在低峰期执行
# - 挂载选项调整
# - 内核参数临时调整(sysctl)
# - 服务重启
# 示例:remount、sysctl -w、service restart

# 风险等级3:高风险,需要审批和备份
# - 文件系统格式化
# - 分区调整
# - 内核参数永久修改
# - 存储配置修改
# 示例:mkfs、fdisk、修改sysctl.conf、RAID配置

# 风险等级4:极高风险,需要完整方案
# - 生产数据删除
# - 存储迁移
# - 底层硬件更换
# 示例:rm -rf数据、pvmove、硬盘热插拔

操作前必查清单

# 1. 确认操作对象
# - 设备/分区路径正确
# - 确认没有正在使用的数据
# - 确认有回滚方案

# 2. 数据备份
# - 重要数据全量备份
# - 配置文件备份
# - 数据库完整备份

# 3. 影响评估
# - 操作影响范围
# - 服务中断时间
# - 是否有备用方案

# 4. 通知相关方
# - 提前通知业务方
# - 通知监控告警组(避免误告警)
# - 通知相关团队

# 5. 执行窗口
# - 低峰期执行
# - 预留回滚时间
# - 多人确认

7.2 备份方案

配置文件备份

# 备份重要配置文件
BACKUP_DIR="/var/backup/config_$(date +%Y%m%d_%H%M%S)"
mkdir -p "$BACKUP_DIR"

# MySQL配置
cp -a /etc/my.cnf "$BACKUP_DIR/"
cp -a /etc/mysql/ "$BACKUP_DIR/" 2>/dev/null

# Redis配置
cp -a /etc/redis/ "$BACKUP_DIR/" 2>/dev/null

# 系统内核参数
cp -a /etc/sysctl.conf "$BACKUP_DIR/"
cp -a /etc/security/limits.conf "$BACKUP_DIR/"

# udev规则
cp -a /etc/udev/rules.d/ "$BACKUP_DIR/"

# 挂载信息
cp -a /etc/fstab "$BACKUP_DIR/"
cp -a /etc/mtab "$BACKUP_DIR/"

echo"配置备份: $BACKUP_DIR"

数据备份脚本

#!/bin/bash
# 数据备份脚本示例

BACKUP_DATE=$(date +%Y%m%d_%H%M%S)
BACKUP_DIR="/var/backup/data_${BACKUP_DATE}"
MOUNT_POINT="/data"
REMOTE_BACKUP="rsync://backup-server::data"

# 创建备份目录
mkdir -p "$BACKUP_DIR"

# 1. 快照备份(如使用LVM)
# 检查VG是否有足够空间创建快照
vg_display | grep "Free  PE"

# 创建LVM快照(需要VG有足够空间)
# lvcreate --size=10G --snapshot --name=data_snap vg_data/lv_data

# 2. rsync备份到本地
rsync -avh --progress "$MOUNT_POINT/""$BACKUP_DIR/local/"

# 3. 备份到远程(如需要)
# rsync -avh --progress "$BACKUP_DIR/" "$REMOTE_BACKUP/"

# 4. 清理旧备份(保留最近7天)
find /var/backup -type d -name "data_*" -mtime +7 -exec rm -rf {} \;

echo"备份完成: $BACKUP_DIR"
ls -lh "$BACKUP_DIR"

7.3 回滚方案

内核参数回滚

# 记录修改前的值
sysctl -a | grep -E "^(vm.|fs.|kernel.)" > /var/backup/sysctl_before_$(date +%Y%m%d).conf

# 修改后验证
sysctl -p

# 如果出问题,逐个恢复
# sysctl -w vm.dirty_ratio=20
# sysctl -w vm.dirty_background_ratio=10

# 或者完全恢复
# sysctl -p /var/backup/sysctl_before_20230511.conf

挂载选项回滚

# 查看当前挂载选项
mount | grep /data

# 如果需要重新挂载(回滚到默认选项)
umount /data
mount /dev/sdb1 /data

# 完全卸载和重新挂载
# 1. 确保没有进程在使用
lsof +D /data

# 2. 停止相关服务
# systemctl stop mysqld

# 3. 卸载
umount /data

# 4. 以原选项重新挂载
mount -o defaults,noatime /dev/sdb1 /data

# 5. 验证
mount | grep /data
df -h /data

文件系统修复

# EXT4文件系统修复
# 注意:修复前必须卸载文件系统!

umount /dev/sdb1
e2fsck -f /dev/sdb1

# 常见修复选项:
# -p: 自动修复(无需确认)
# -f: 强制检查(即使文件系统看起来正常)
# -y: 所有问题都自动回答yes

# 如果有坏道,使用-n找出坏道但不修复
e2fsck -n /dev/sdb1

# XFS文件系统修复
# XFS不能使用e2fsck,必须用xfs_repair
umount /dev/sdb1
xfs_repair /dev/sdb1

# xfs_repair选项:
# -L: 强制日志清零(最后手段,可能丢数据)
# -m: 指定内存限制
# -v: 详细输出

服务回滚

# MySQL回滚步骤

# 1. 停止MySQL
systemctl stop mysqld

# 2. 备份当前数据
cp -a /var/lib/mysql /var/backup/mysql_before_rollback

# 3. 恢复配置文件
cp -a /var/backup/my.cnf /etc/my.cnf

# 4. 恢复数据(如需要)
# 如果有全量备份:
# tar -xzf /var/backup/mysql_full_backup.tar.gz -C /var/lib/mysql/

# 5. 启动MySQL
systemctl start mysqld

# 6. 验证
mysql -e "SELECT VERSION();"
mysql -e "SHOW STATUS LIKE 'Uptime';"

7.4 灰度验证流程

配置变更灰度验证

# 1. 先在测试环境验证
# 所有配置变更先在测试环境验证通过

# 2. 单台机器验证
# 选择非核心业务机器先验证
# 应用监控观察5-10分钟

# 3. 扩大范围
# 确认无误后再扩大到更多机器

# 4. 全量生效
# 确认稳定后全部生效

# 验证命令示例:
# 检查服务状态
systemctl status mysqld
mysql -e "SELECT VERSION();"

# 检查连接数
mysql -e "SHOW STATUS LIKE 'Threads_connected';"

# 检查查询性能
mysql -e "SHOW GLOBAL STATUS LIKE 'Slow_queries';"

# 观察应用日志
tail -f /var/log/myapp/error.log

# 观察系统资源
top -b -n 1 | head -20
iostat -xcz 1 5

第八章 实战案例复盘

案例1:MySQL数据库响应延迟

问题背景某电商网站数据库服务器,MySQL 5.7,16核CPU,64GB内存,数据盘为RAID10(4块SSD)。问题现象:网站在促销期间响应缓慢,SQL执行时间从正常100ms增加到3000ms+,监控显示CPU的iowait达到45%。

排查过程

# 步骤1:确认iowait高
top -b -n 1
#%Cpu(s): 12.3 us,  6.5 sy,  0.0 ni, 35.7 id, 45.5 wa,  0.0 hi,  0.0 si,  0.0 st
# iowait 45.5%,确认是IO瓶颈

# 步骤2:定位磁盘
iostat -xcz 1
# Device:  %util
# sdb      98.45  # 数据盘%util达到98%,确认是这块盘的问题

# 步骤3:定位进程
iotop -b -n 5 | grep -v "Total" | sort -k10 -rn | head -10
# mysqld占用了95%以上的IO

# 步骤4:分析MySQL IO特征
pidstat -d -p $(pgrep -x mysqld) 1 10
# 写IO为主,每秒写入量约80MB

# 步骤5:检查MySQL状态
mysql -e "SHOW ENGINE INNODB STATUS\G" | grep -A10 "LOG"
# 发现Log sequence number增长很快,redo log写入频繁

mysql -e "SHOW GLOBAL STATUS LIKE 'Innodb_os_log%';"
# Innodb_os_log_written值很大,说明redo log写入量大

# 步骤6:检查innodb_flush_log_at_trx_commit
mysql -e "SHOW VARIABLES LIKE 'innodb_flush_log_at_trx_commit';"
# 值为1,每次事务提交都刷日志

# 步骤7:检查slow_query_log
mysql -e "SHOW VARIABLES LIKE 'slow_query_log';"
mysql -e "SHOW GLOBAL STATUS LIKE 'Slow_queries';"
# 发现大量超过2秒的查询

根因分析

  1. innodb_flush_log_at_trx_commit=1 导致每次事务提交都刷日志到磁盘
  2. 促销期间事务量激增,大量redo log写入造成IO瓶颈
  3. 4块SSD的RAID10理论IOPS足够,但小事务频繁刷日志导致延迟累积

优化方案

# 方案1:调整刷日志策略(需要评估数据安全风险)
# 编辑my.cnf
[mysqld]
innodb_flush_log_at_trx_commit = 2  # 折中方案:每秒刷一次日志
# 注意:此方案最多丢失1秒的事务数据,需要业务确认可接受

# 方案2:增加redo log文件大小
[mysqld]
innodb_log_file_size = 4G  # 增大redo log,减少检查点刷新
innodb_log_files_in_group = 4

# 方案3:优化应用事务逻辑
# - 合并小事务,减少事务数量
# - 使用批量插入
# - 非关键操作异步化

# 方案4:增加IO能力
# - 考虑使用电池备份的RAID卡缓存
# - 或升级到更高性能的NVMe SSD

优化后验证

# 1. 修改配置后重启MySQL
systemctl restart mysqld

# 2. 监控IO指标
iostat -xcz 1  # 观察%util是否下降

# 3. 观察SQL响应时间
mysql -e "SHOW GLOBAL STATUS LIKE 'Slow_queries';"
# 确认慢查询数量下降

# 4. 监控redo log写入量
watch -n 1 'mysql -e "SHOW GLOBAL STATUS LIKE \"Innodb_os_log%\"";'

# 5. 业务验证
# 联系业务方确认响应时间改善

经验总结

  • 数据库刷日志策略对IO影响巨大,需要在性能和数据安全间权衡
  • 事务量激增场景需要考虑批量事务优化
  • 监控要覆盖iowait和磁盘IO指标

案例2:日志服务器写入阻塞

问题背景日志收集服务器,使用rsyslog收集多台应用服务器日志,写入到本地磁盘。问题现象:日志写入延迟增加,应用服务器开始堆积日志无法发送,监控显示磁盘%util持续在95%以上。

排查过程

# 步骤1:确认磁盘状态
iostat -xcz 1
# Device:  %util   await   avgrq-sz
# sda      98.23   156.78    8.45   # 几乎满负荷

# 步骤2:分析IO类型
pidstat -d 1 10 | head -30
# rsyslogd进程写IO很高

# 步骤3:检查日志量
ls -lh /var/log/ | head -20
# 多个日志文件很大

# 查看当日日志增量
du -sh /var/log/app/*
# 某个应用日志单日增长50GB

# 步骤4:检查日志轮转配置
cat /etc/logrotate.conf
cat /etc/logrotate.d/rsyslog

# 发现问题:
# - 日志轮转没有配置compress,导致日志文件很大
# - 日志保留周期过长,占用大量空间

根因分析

  1. 大量日志文件顺序写入,但没有开启压缩
  2. 日志轮转间隔过长,一次性大量写入造成IO高峰
  3. /var/log 在机械硬盘上,大量小IO聚合效率低

优化方案

# 1. 优化日志轮转配置
cat > /etc/logrotate.d/app << 'EOF'
/var/log/app/*.log {
    daily              # 每天轮转
    rotate 7           # 保留7天
    compress           # 压缩旧日志
    delaycompress      # 延迟压缩(保留最近一个不压缩)
    missingok          # 忽略丢失文件
    notifempty         # 空文件不轮转
    create 0644 root root  # 轮转后创建新文件权限
    sharedscripts      # 所有日志轮转后执行一次脚本
    postrotate
        /bin/kill -HUP $(cat /var/run/rsyslogd.pid 2>/dev/null) || true
    endscript
}
EOF

# 2. 将日志目录迁移到SSD(如果可用)
# 检查是否有SSD可用
lsblk
# 如果有未使用的SSD /dev/sdb

# 迁移日志到SSD
mount -t xfs -o noatime,nodiratime /dev/sdb1 /var/log_ssd
rsync -avh /var/log/ /var/log_ssd/
mount --bind /var/log_ssd/app /var/log/app

# 3. rsyslog优化配置
cat >> /etc/rsyslog.conf << 'EOF'
# 启用内存队列,避免磁盘IO阻塞
$imjournalRatelimitInterval 1
$imjournalRatelimitBurst 5000

# 使用异步写入
$ActionFileEnableSync off

# 缓冲模式
$OutChannel diskqFile, /var/spool/rsyslog/diskq.bin, 10M
EOF

# 4. 创建rsyslog目录
mkdir -p /var/spool/rsyslog
chown syslog:syslog /var/spool/rsyslog

# 5. 重启rsyslog
systemctl restart rsyslog

优化后验证

# 1. 观察IO指标
iostat -xcz 1
# %util应该下降到50%以下

# 2. 检查日志轮转是否正常
logrotate -d /etc/logrotate.d/app  # 调试模式查看是否正常

# 3. 检查rsyslog队列
ls -lh /var/spool/rsyslog/

# 4. 确认应用日志正常写入
tail -f /var/log/app/application.log

经验总结

  • 日志系统IO优化优先考虑减少写入量和写入频率
  • 日志轮转配置一定要开启压缩
  • 高写入场景优先使用SSD

案例3:高并发小文件场景

问题背景图片缓存服务器,存储大量小图片文件(约4-8KB/文件),共5000万文件。文件系统EXT4,存储在RAID5(12块4TB HDD)。问题现象:图片读取延迟高,CPU iowait达30%,单目录文件数过多导致ls和rm命令都很慢。

排查过程

# 步骤1:检查inode使用
df -i
# Filesystem       IUse  IFree IUse% Mounted on
# /dev/sdb1        50M      0   100%  /data  # inode用尽!

# 步骤2:查看目录结构
time ls /data/images/ | wc -l
# 单个目录有500万文件

# 步骤3:分析IO
iostat -xcz 1
# avgrq-sz约4KB(小文件特征明显)

# 步骤4:检查是否元数据瓶颈
# 小文件+大量文件导致元数据操作成为瓶颈

# 问题总结:
# 1. inode耗尽,无法创建新文件
# 2. 单目录文件数过多,元数据操作效率低
# 3. EXT4在小文件场景元数据开销大

解决方案

# 方案1:重做文件系统,扩大inode数量
# 注意:会丢失所有数据!

# 1. 全量备份(如果有空间)
mkdir -p /mnt/backup
rsync -avh /data/ /mnt/backup/

# 2. 卸载并重新格式化,指定更多inode
umount /data
# -i bytes-per-inode:每多少字节分配一个inode
# 默认是16384字节创建一个inode
# 如果平均文件4KB,可以设为4096
mkfs.ext4 -i 4096 /dev/sdb1

# 3. 重新挂载
mount /dev/sdb1 /data

# 4. 恢复数据
rsync -avh /mnt/backup/ /data/

# 方案2:使用XFS文件系统
umount /data
mkfs.xfs -f /dev/sdb1
mount /dev/sdb1 /data

# XFS优势:
# - inode动态分配,不预先占用空间
# - 大目录遍历性能更好
# - 随机写性能优于EXT4

# 方案3:优化目录结构(湖仓一体思路)
# 将大目录拆分成多级目录

# 创建哈希目录结构
mkdir -p /data/images/{0..9}/{0..9}/{0..9}

# 编写脚本计算目标目录
cat > /usr/local/bin/get_image_path.sh << 'EOF'
#!/bin/bash
# 根据文件ID计算存储路径
# 将文件ID的哈希值分散到多级目录
file_id=$1
hash=$(echo$file_id | md5sum | cut -c1)
dir1=${hash:0:1}
dir2=${hash:1:1}
dir3=${hash:2:1}
echo"${dir1}/${dir2}/${dir3}/${file_id}"
EOF
chmod +x /usr/local/bin/get_image_path.sh

# 方案4:使用对象存储替代本地文件系统
# 考虑使用MinIO、Ceph等分布式存储
# 优点:横向扩展、冗余可靠
# 缺点:需要改代码

优化后验证

# 检查inode使用
df -i
# IFree应该大幅增加

# 测试目录遍历性能
time ls /data/images/0/0/0/ | head -1000

# 测试创建文件性能
time touch /data/images/test_file_$$

# 检查XFS特性
xfs_info /data

# 监控IO改善情况
iostat -xcz 1
# avgrq-sz和await应该改善

经验总结

  • 小文件场景要提前规划inode数量
  • 单目录文件数不宜超过10万
  • XFS相比EXT4更适合小文件场景
  • 大规模文件存储考虑对象存储方案

第九章 总结与检查清单

9.1 IO优化核心要点

理解IO性能三要素

IOPS × 平均IO大小 = 吞吐量
延迟 × 并发度 = 响应时间

选择合适的存储介质

  • 随机IO为主 → SSD,IOPS优先
  • 顺序IO为主 → 大容量HDD或SSD,吞吐量优先
  • 延迟敏感 → NVMe SSD

选择合适的文件系统

  • XFS:通用场景,大文件高并发
  • EXT4:兼容性要求高,不需要高级特性
  • tmpfs/ramfs:临时文件和缓存

优化IO调度器

  • SSD → noop或mq-deadline
  • HDD → deadline
  • 数据库 → deadline

优化挂载选项

  • 高性能场景 → noatime,nodiratime
  • 需要数据安全 → 保持默认barrier

优化内核参数

  • 脏页回写参数(vm.dirty_*)
  • IO队列深度(nr_requests)
  • 预读值(read_ahead_kb)

应用层优化

  • 批量IO操作
  • 异步IO
  • 合理使用缓存
  • 优化SQL和索引

9.2 IO优化检查清单

新服务器部署检查

# [ ] 1. 存储规划
#     - [ ] 根据IO特征选择存储类型
#     - [ ] 合理分区(数据、日志、临时文件分开)
#     - [ ] 文件系统选择(XFS或EXT4)

# [ ] 2. 调度器配置
#     - [ ] SSD使用noop调度器
#     - [ ] HDD使用deadline调度器
#     - [ ] 验证配置生效:cat /sys/block/*/queue/scheduler

# [ ] 3. 挂载选项
#     - [ ] 生产环境使用noatime
#     - [ ] 数据目录合理设置选项
#     - [ ] 验证:mount | grep /data

# [ ] 4. 内核参数
#     - [ ] 根据业务调整脏页参数
#     - [ ] 验证:sysctl -a | grep vm.dirty

# [ ] 5. 监控
#     - [ ] 部署监控 exporter
#     - [ ] 配置告警阈值
#     - [ ] 建立性能基线

日常巡检检查

# [ ] 1. 磁盘使用率
#     - [ ] df -h 检查空间使用 < 80%
#     - [ ] df -i 检查inode使用

# [ ] 2. IO性能
#     - [ ] iostat -xcz 1 检查%util < 80%
#     - [ ] 检查await在正常范围

# [ ] 3. 进程IO
#     - [ ] pidstat -d 1 检查异常IO进程
#     - [ ] iotop 检查高IO进程

# [ ] 4. 系统日志
#     - [ ] dmesg | grep -i error 检查硬件错误
#     - [ ] 查看系统日志中的IO相关警告

# [ ] 5. 健康状态
#     - [ ] smartctl -H 检查磁盘健康
#     - [ ] RAID卡状态(如使用)

问题排查检查

# [ ] 1. 确认IO问题
#     - [ ] top查看iowait是否高
#     - [ ] iostat确认是磁盘问题

# [ ] 2. 定位瓶颈
#     - [ ] iostat确认哪块磁盘
#     - [ ] pidstat/iotop确认哪个进程

# [ ] 3. 分析根因
#     - [ ] 查看IO类型(读/写)
#     - [ ] 查看IO大小(avgrq-sz)
#     - [ ] 查看队列深度(avgqu-sz)

# [ ] 4. 制定方案
#     - [ ] 根据根因选择优化方向
#     - [ ] 评估风险和影响
#     - [ ] 准备回滚方案

# [ ] 5. 实施验证
#     - [ ] 灰度验证
#     - [ ] 监控指标改善
#     - [ ] 业务验证正常

9.3 常见问题速查

问题现象
可能原因
快速检查命令
解决方向
%util高+await高
设备能力达到上限
iostat -xcz 1
升级存储/分散IO
avgqu-sz高+await高
请求堆积
iostat -xcz 1
优化IO/增加并发
avgrq-sz很小
大量小IO
iostat -xcz 1
批量IO/合并请求
iowait高但%util低
元数据瓶颈
iostat -xcz 1
优化文件系统/使用SSD
延迟抖动
存储不稳定/竞争
dmesg; iostat -x 1
检查硬件/隔离IO
inode耗尽
文件数过多
df -i
重新格式化/拆分目录
空间够但IO慢
碎片化
e2fsck/iostat
文件系统检查/优化

9.4 推荐工具链

监控工具

# 基础监控
iostat          # IO统计
pidstat         # 进程级IO
iotop           # 交互式IO监控

# 高级监控
sar             # 历史数据分析
nmon/atop       # 综合系统监控

# 监控平台
Prometheus + node_exporter  # 指标收集
Grafana         # 可视化
AlertManager    # 告警

分析工具

# 基准测试
fio              # 存储基准测试
bonnie++         # 文件系统测试

# 性能分析
blktrace         # 块IO追踪
bpftrace         # 高级IO分析
perf             # 系统性能分析

故障排查

# 日志查看
dmesg           # 内核日志
/var/log/messages  # 系统日志
/var/log/kern.log  # 内核详细日志

# 工具
lsof            # 查看文件句柄
strace          # 系统调用追踪
ltrace          # 库调用追踪

附录:关键命令速查

iostat 常用命令

# 每秒刷新,显示CPU和设备
iostat 1

# 每2秒刷新一次,共5次
iostat 2 5

# 只显示设备,不显示CPU
iostat -d

# 显示扩展统计
iostat -x

# 显示MB为单位
iostat -m

# 查看特定设备
iostat -d sda sdb

# 查看特定时间段的统计
iostat -x 1 5 | awk '/^Device:/ {p=1} p'

iotop 常用命令

# 交互式显示
iotop

# 非交互式,一次性
iotop -b

# 非交互,每秒一次,共10次
iotop -b -n 10 -d 1

# 只显示有IO的进程
iotop -b -o

# 显示特定用户的IO
iotop -b -u mysql

pidstat 常用命令

# 每秒显示进程IO
pidstat -d 1

# 显示特定进程的IO
pidstat -d -p 12345 1

# 显示所有进程的IO,每秒一次
pidstat -d 1 1

# 显示扩展统计
pidstat -dx 1

fio 常用命令

# 4K随机读测试
fio --name=randread --ioengine=libaio --iodepth=4 --rw=randread --bs=4k --size=1G --runtime=60 --time_based=1 --filename=/dev/sdb1

# 顺序写测试
fio --name=seqwrite --ioengine=libaio --iodepth=16 --rw=write --bs=128k --size=2G --runtime=60 --time_based=1 --filename=/dev/sdb1

# 混合读写测试(70%读)
fio --name=mixrw --ioengine=libaio --iodepth=4 --rw=randrw --rwmixread=70 --bs=4k --size=1G --runtime=60 --time_based=1 --filename=/dev/sdb1

sysctl 常用参数

# 查看所有IO相关参数
sysctl -a | grep -E "^(vm.|fs.)"

# 临时修改dirty_ratio
sysctl -w vm.dirty_ratio=40

# 永久生效
echo"vm.dirty_ratio = 40" >> /etc/sysctl.conf
sysctl -p

# 查看当前值
sysctl vm.dirty_ratio

最新文章

随机文章

基本 文件 流程 错误 SQL 调试
  1. 请求信息 : 2026-07-03 20:46:16 HTTP/2.0 GET : https://f.mffb.com.cn/a/492915.html
  2. 运行时间 : 1.569511s [ 吞吐率:0.64req/s ] 内存消耗:4,813.87kb 文件加载:140
  3. 缓存信息 : 0 reads,0 writes
  4. 会话信息 : SESSION_ID=c902702d8cafe7688bb2084244ce5428
  1. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/public/index.php ( 0.79 KB )
  2. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/autoload.php ( 0.17 KB )
  3. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/composer/autoload_real.php ( 2.49 KB )
  4. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/composer/platform_check.php ( 0.90 KB )
  5. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/composer/ClassLoader.php ( 14.03 KB )
  6. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/composer/autoload_static.php ( 4.90 KB )
  7. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-helper/src/helper.php ( 8.34 KB )
  8. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-validate/src/helper.php ( 2.19 KB )
  9. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-orm/src/helper.php ( 1.47 KB )
  10. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-orm/stubs/load_stubs.php ( 0.16 KB )
  11. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/Exception.php ( 1.69 KB )
  12. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-container/src/Facade.php ( 2.71 KB )
  13. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/symfony/deprecation-contracts/function.php ( 0.99 KB )
  14. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/symfony/polyfill-mbstring/bootstrap.php ( 8.26 KB )
  15. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/symfony/polyfill-mbstring/bootstrap80.php ( 9.78 KB )
  16. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/symfony/var-dumper/Resources/functions/dump.php ( 1.49 KB )
  17. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-dumper/src/helper.php ( 0.18 KB )
  18. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/symfony/var-dumper/VarDumper.php ( 4.30 KB )
  19. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/App.php ( 15.30 KB )
  20. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-container/src/Container.php ( 15.76 KB )
  21. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/psr/container/src/ContainerInterface.php ( 1.02 KB )
  22. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/app/provider.php ( 0.19 KB )
  23. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/Http.php ( 6.04 KB )
  24. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-helper/src/helper/Str.php ( 7.29 KB )
  25. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/Env.php ( 4.68 KB )
  26. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/app/common.php ( 0.03 KB )
  27. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/helper.php ( 18.78 KB )
  28. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/Config.php ( 5.54 KB )
  29. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/config/app.php ( 0.95 KB )
  30. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/config/cache.php ( 0.78 KB )
  31. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/config/console.php ( 0.23 KB )
  32. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/config/cookie.php ( 0.56 KB )
  33. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/config/database.php ( 2.48 KB )
  34. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/facade/Env.php ( 1.67 KB )
  35. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/config/filesystem.php ( 0.61 KB )
  36. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/config/lang.php ( 0.91 KB )
  37. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/config/log.php ( 1.35 KB )
  38. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/config/middleware.php ( 0.19 KB )
  39. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/config/route.php ( 1.89 KB )
  40. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/config/session.php ( 0.57 KB )
  41. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/config/trace.php ( 0.34 KB )
  42. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/config/view.php ( 0.82 KB )
  43. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/app/event.php ( 0.25 KB )
  44. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/Event.php ( 7.67 KB )
  45. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/app/service.php ( 0.13 KB )
  46. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/app/AppService.php ( 0.26 KB )
  47. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/Service.php ( 1.64 KB )
  48. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/Lang.php ( 7.35 KB )
  49. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/lang/zh-cn.php ( 13.70 KB )
  50. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/initializer/Error.php ( 3.31 KB )
  51. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/initializer/RegisterService.php ( 1.33 KB )
  52. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/services.php ( 0.14 KB )
  53. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/service/PaginatorService.php ( 1.52 KB )
  54. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/service/ValidateService.php ( 0.99 KB )
  55. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/service/ModelService.php ( 2.04 KB )
  56. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-trace/src/Service.php ( 0.77 KB )
  57. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/Middleware.php ( 6.72 KB )
  58. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/initializer/BootService.php ( 0.77 KB )
  59. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-orm/src/Paginator.php ( 11.86 KB )
  60. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-validate/src/Validate.php ( 63.20 KB )
  61. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-orm/src/Model.php ( 23.55 KB )
  62. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-orm/src/model/concern/Attribute.php ( 21.05 KB )
  63. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-orm/src/model/concern/AutoWriteData.php ( 4.21 KB )
  64. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-orm/src/model/concern/Conversion.php ( 6.44 KB )
  65. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-orm/src/model/concern/DbConnect.php ( 5.16 KB )
  66. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-orm/src/model/concern/ModelEvent.php ( 2.33 KB )
  67. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-orm/src/model/concern/RelationShip.php ( 28.29 KB )
  68. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-helper/src/contract/Arrayable.php ( 0.09 KB )
  69. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-helper/src/contract/Jsonable.php ( 0.13 KB )
  70. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-orm/src/model/contract/Modelable.php ( 0.09 KB )
  71. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/Db.php ( 2.88 KB )
  72. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-orm/src/DbManager.php ( 8.52 KB )
  73. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/Log.php ( 6.28 KB )
  74. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/Manager.php ( 3.92 KB )
  75. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/psr/log/src/LoggerTrait.php ( 2.69 KB )
  76. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/psr/log/src/LoggerInterface.php ( 2.71 KB )
  77. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/Cache.php ( 4.92 KB )
  78. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/psr/simple-cache/src/CacheInterface.php ( 4.71 KB )
  79. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-helper/src/helper/Arr.php ( 16.63 KB )
  80. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/cache/driver/File.php ( 7.84 KB )
  81. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/cache/Driver.php ( 9.03 KB )
  82. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/contract/CacheHandlerInterface.php ( 1.99 KB )
  83. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/app/Request.php ( 0.09 KB )
  84. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/Request.php ( 55.78 KB )
  85. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/app/middleware.php ( 0.25 KB )
  86. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/Pipeline.php ( 2.61 KB )
  87. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-trace/src/TraceDebug.php ( 3.40 KB )
  88. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/middleware/SessionInit.php ( 1.94 KB )
  89. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/Session.php ( 1.80 KB )
  90. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/session/driver/File.php ( 6.27 KB )
  91. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/contract/SessionHandlerInterface.php ( 0.87 KB )
  92. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/session/Store.php ( 7.12 KB )
  93. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/Route.php ( 23.73 KB )
  94. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/route/RuleName.php ( 5.75 KB )
  95. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/route/Domain.php ( 2.53 KB )
  96. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/route/RuleGroup.php ( 22.43 KB )
  97. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/route/Rule.php ( 26.95 KB )
  98. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/route/RuleItem.php ( 9.78 KB )
  99. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/route/app.php ( 1.72 KB )
  100. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/facade/Route.php ( 4.70 KB )
  101. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/route/dispatch/Controller.php ( 4.74 KB )
  102. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/route/Dispatch.php ( 10.44 KB )
  103. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/app/controller/Index.php ( 4.81 KB )
  104. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/app/BaseController.php ( 2.05 KB )
  105. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-orm/src/facade/Db.php ( 0.93 KB )
  106. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-orm/src/db/connector/Mysql.php ( 5.44 KB )
  107. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-orm/src/db/PDOConnection.php ( 52.47 KB )
  108. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-orm/src/db/Connection.php ( 8.39 KB )
  109. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-orm/src/db/ConnectionInterface.php ( 4.57 KB )
  110. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-orm/src/db/builder/Mysql.php ( 16.58 KB )
  111. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-orm/src/db/Builder.php ( 24.06 KB )
  112. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-orm/src/db/BaseBuilder.php ( 27.50 KB )
  113. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-orm/src/db/Query.php ( 15.71 KB )
  114. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-orm/src/db/BaseQuery.php ( 45.13 KB )
  115. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-orm/src/db/concern/TimeFieldQuery.php ( 7.43 KB )
  116. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-orm/src/db/concern/AggregateQuery.php ( 3.26 KB )
  117. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-orm/src/db/concern/ModelRelationQuery.php ( 20.07 KB )
  118. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-orm/src/db/concern/ParamsBind.php ( 3.66 KB )
  119. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-orm/src/db/concern/ResultOperation.php ( 7.01 KB )
  120. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-orm/src/db/concern/WhereQuery.php ( 19.37 KB )
  121. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-orm/src/db/concern/JoinAndViewQuery.php ( 7.11 KB )
  122. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-orm/src/db/concern/TableFieldInfo.php ( 2.63 KB )
  123. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-orm/src/db/concern/Transaction.php ( 2.77 KB )
  124. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/log/driver/File.php ( 5.96 KB )
  125. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/contract/LogHandlerInterface.php ( 0.86 KB )
  126. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/log/Channel.php ( 3.89 KB )
  127. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/event/LogRecord.php ( 1.02 KB )
  128. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-helper/src/Collection.php ( 16.47 KB )
  129. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/facade/View.php ( 1.70 KB )
  130. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/View.php ( 4.39 KB )
  131. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/Response.php ( 8.81 KB )
  132. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/response/View.php ( 3.29 KB )
  133. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/Cookie.php ( 6.06 KB )
  134. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-view/src/Think.php ( 8.38 KB )
  135. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/contract/TemplateHandlerInterface.php ( 1.60 KB )
  136. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-template/src/Template.php ( 46.61 KB )
  137. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-template/src/template/driver/File.php ( 2.41 KB )
  138. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-template/src/template/contract/DriverInterface.php ( 0.86 KB )
  139. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/runtime/temp/067d451b9a0c665040f3f1bdd3293d68.php ( 11.98 KB )
  140. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-trace/src/Html.php ( 4.42 KB )
  1. CONNECT:[ UseTime:0.000917s ] mysql:host=127.0.0.1;port=3306;dbname=f_mffb;charset=utf8mb4
  2. SHOW FULL COLUMNS FROM `fenlei` [ RunTime:0.001622s ]
  3. SELECT * FROM `fenlei` WHERE `fid` = 0 [ RunTime:0.101405s ]
  4. SELECT * FROM `fenlei` WHERE `fid` = 63 [ RunTime:0.101230s ]
  5. SHOW FULL COLUMNS FROM `set` [ RunTime:0.001531s ]
  6. SELECT * FROM `set` [ RunTime:0.101319s ]
  7. SHOW FULL COLUMNS FROM `article` [ RunTime:0.000995s ]
  8. SELECT * FROM `article` WHERE `id` = 492915 LIMIT 1 [ RunTime:0.101206s ]
  9. UPDATE `article` SET `lasttime` = 1783082777 WHERE `id` = 492915 [ RunTime:0.701303s ]
  10. SELECT * FROM `fenlei` WHERE `id` = 67 LIMIT 1 [ RunTime:0.000897s ]
  11. SELECT * FROM `article` WHERE `id` < 492915 ORDER BY `id` DESC LIMIT 1 [ RunTime:0.037191s ]
  12. SELECT * FROM `article` WHERE `id` > 492915 ORDER BY `id` ASC LIMIT 1 [ RunTime:0.100264s ]
  13. SELECT * FROM `article` WHERE `id` < 492915 ORDER BY `id` DESC LIMIT 10 [ RunTime:0.063141s ]
  14. SELECT * FROM `article` WHERE `id` < 492915 ORDER BY `id` DESC LIMIT 10,10 [ RunTime:0.045521s ]
  15. SELECT * FROM `article` WHERE `id` < 492915 ORDER BY `id` DESC LIMIT 20,10 [ RunTime:0.024899s ]
1.575681s