事情本身不复杂,线索都在日志里。应用日志按行同步刷盘,iostat 里 w/s 只有三千但 w_await 到 12ms,接口偶发超时,机器用的是普通云盘不是 ESSD,系统 CentOS 7.9。

第一反应是「文件系统日志模式是 data=journal,写两次」,验证下来不成立。

真正麻烦的地方在于,几个原因的现象几乎一样。每条日志都调用 fsync,每次都要等落盘。也可能是日志文件和数据库数据在同一块盘上。

不容易想到的是,目录项更新也同步,多出一次元数据写。

动手时先看进程的 fsync 调用频率

strace -f -c -p $(pgrep -f order-service)

接着把日志改成缓冲写并定时刷盘

grep -n 'sync\|fsync' /opt/app/conf/logback.xml | head

然后把日志目录迁到独立云盘

df -h /var/log && lsblk -o NAME,SIZE,MOUNTPOINT

复核写入延迟与抖动幅度

iostat -xmd 1 10 /dev/vdb

恢复的判定其实很直接。fsync 次数降到每秒几十次,w_await 稳定在 2ms 以内,接口的超时告警随之消失。

这里还有个坑。日志落盘要按重要性分级,审计日志同步写、业务日志缓冲写;fsync 的代价在普通云盘上尤其明显。这类问题最好一次改到位,反复小改反而容易把原因搅混。

作者 9823189