夜深人静,结束了一天的工作,拖着疲惫的身体,我终于躺在了床上,闭上眼睛,享受着宁静的床。 "叮铃铃,叮铃铃",急促的电话铃声,划破安静,我努力睁开眼睛,看了下时间,零点十分。 又是那该死的幽灵,我只好爬起来,冲了杯咖啡,打开电脑,为抓取幽灵做好前期的准备。
问题现象
高可用服务突然因为心跳超时导致将整个节点给隔离了。 首先怀疑是网络问题,先查有没有网络异常。ip addr show看了下,隔离的节点网口状态都正常;dmesg -T看了下,未发现最近时间有网口异常的记录;sar -n EDEV看了下,所有网口都没有错误的记录。由此,基本排除了网络问题。 其次怀疑是资源问题,查cpu资源,sar看了下,未发现有cpu资源突增;查内存资源,sar -r看了下,未发现内存资源有突增;查io资源,sar -d -p看了下,发现系统盘的await值飙升到了6000+,妥妥的慢盘状态。
分析
发现明显异常,但磁盘io与网络逻辑上独立,所以需要快速验证下关联性。 使用工具模拟系统盘慢盘的状态,确实触发了高可用服务的心跳超时。再回到问题时间段,分析可能造成读写磁盘的压力增大的原因,发现logrotate的切割会在这个时间段触发。 再进行logrotate切割与磁盘io压力验证。 压测脚本:拷贝5个512M的文件到目标目录,日志切割(压缩后gz文件大小502M) 结果: 三星盘:logrotate触发时,await平均600-700,最大1000+,同时发现脏页存在快速增长和下刷的情况 英极盘:logrotate触发时,await平均2000,最大2300+,同时发现脏页存在快速增长和下刷的情况 幽灵抓到了!logrotate触发脏页快速增大,进而触发了系统盘集中下刷数据,系统盘产生慢盘,进而导致高可用服务的bug被触发,影响到了网络心跳监控进程的逻辑。
处理建议
现场环境升级服务通常比较难,在不升级服务解决高可用服务bug的前提下,来缓解问题。
脏页回写导致磁盘压力大、影响业务进程,通常意味着脏页堆积水位过高 ,触发了回写 时压力集中。你的核心目标应该是让回写从"集中爆发"变为"持续平滑" 。 针对这个问题,解决方案可以分为四层:临时处理、系统级调优、关键进程隔离、以及文件系统层优化。
- 临时处理
-
日志切割配置分散:将logrotate的切割从整体划分为多个部分,分摊切割压力
-
减少缓存使用概率: 减少写缓存的使用概率
编辑 /etc/fstab,添加 sync
/dev/sda1 /data ext4 defaults,sync 0 0
重新挂载生效
mount -o remount,rw,sync /
- 系统级调优
这是解决脏页回写压力的根本手段 。核心思路是降低触回写的水位、提高回写频率
# 后台回写阈值:达到此值开始异步刷盘,建议 3-5%(原默认10%)
vm.dirty_background_ratio = 5
# 前台阻塞阈值:达到此值进程写入会被阻塞,建议 10-15%(原默认20%)
vm.dirty_ratio = 10
# 回写线程唤醒间隔:缩短至 1秒(原默认5秒),让回写更平滑
vm.dirty_writeback_centisecs = 100
# 脏页存活时间:缩短至 10秒(原默认30秒),避免脏页堆积过久
vm.dirty_expire_centisecs = 1000
# 元数据缓存:适当回收内存压力(默认100,内存紧张可加大)
vm.vfs_cache_pressure = 200
- 关键进程隔离
如果系统中有多块磁盘 ,且只有某块盘(如数据盘)压力大 ,而系统盘或其它盘正常 ,可以针对单个块设备 进行回写带宽配额限制,避免"一台机器受影响,全盘应用都卡"。 这是比全局调优更精细、更有效的手段 ,尤其适合数据库、日志服务等独占磁盘的场景
查看设备号并设置回写配额
# 查看设备 major:minor
lsblk
# 例如 nvme0n1 的 MAJ:MIN = 259:0
# 设置该设备最低回写带宽配额(保障其回写能力)
echo 20 > /sys/class/bdi/259:0/min_ratio
# 限制该设备最大回写带宽配额(防止其抢占系统盘带宽)
echo 60 > /sys/class/bdi/259:0/max_ratio
作用解析:
| 参数 | 作用 | 典型场景 |
|---|---|---|
min_ratio |
保障该设备最少获得X%的系统回写带宽 | 重要业务盘,避免被饿死 |
max_ratio |
限制该设备最多占用X%的系统回写带宽 | 日志盘、非关键盘,防止干扰系统盘 |
⚠️ 注意 :该特性需要内核支持(Alibaba Cloud Linux 全系支持,主流发行版如RHEL/CentOS 8+ 部分支持),若不支持则/sys/class/bdi/下可能无此文件
-
文件系统层优化 I/O调度器
-
SSD/NVMe :使用
none或noop(减少调度开销) -
HDD :使用
deadline(降低延迟)echo deadline > /sys/block/sda/queue/scheduler
🚫 常见误区(请一定避开)
| 错误操作 | 后果 | 正确做法 |
|---|---|---|
频繁执行 echo 3 > drop_caches |
破坏缓存命中率,I/O 反升 | 仅用于基准测试或紧急内存释放 |
盲目调大 dirty_ratio 至 40%+ |
回写时系统长时间卡死 | 普通服务器建议 ≤20% |
| 认为调小脏页阈值一定会提升性能 | 阈值过小,频繁刷盘,写入性能下降 | 根据写多读少场景取舍 |
✅ 总结:推荐优先级方案
| 方案 | 难度 | 见效速度 | 适用场景 |
|---|---|---|---|
| 1. 全局脏页阈值调优 | ⭐⭐ | 立即 | 所有场景首选 |
| 2. 单盘回写配额控制 | ⭐⭐⭐ | 立即 | 多磁盘、关键业务隔离 |
| 3. I/O调度器调优 | ⭐⭐ | 立即 | SSD/HDD 混合 |
| 4. 手动 drop_caches | ⭐ | 瞬间 | 应急止血 |