游戏卡顿白皮书 › L11 磁盘
同步写日志 Synchronous logging
原因 ID dk-sync-log · 主责 研发团队·服务器开发 · 配合 运维团队·系统运维
在含图示和实验的完整版中打开此卡片 →
游戏线程每写一行日志都要等磁盘完成,磁盘一忙,游戏逻辑也跟着停住。
起因 在游戏线程里直接把战斗、交易日志写入文件 → 结果 要求确保落盘(fsync),或 OS 的写缓冲(页缓存)达到上限时,磁盘一忙,一次写入就要几十 ms → 画面表现 日志多的战斗中顿一下
- 症状
- 一卡一卡, 卡住
- 因素
- 停顿
- 谁会遇到
- 特定地点/分线, 全服
- 何时出现
- 人多的时候
- 负责方
- 主责 研发团队·服务器开发 · 配合 运维团队·系统运维
- 研发团队要做的事
- 异步日志(内存缓冲 + 独立线程),减少日志量,不在游戏线程里调用 fsync。
- 运维团队要做的事
- 日志轮转和压缩以较低的 I/O 优先级运行,日志与数据放在不同磁盘,监控磁盘写入延迟。
- 监控图上
- 偶发随机尖峰 · 服务器 tick 耗时、磁盘写入延迟
- 查看位置
- 把 iostat -x 1 的 w_await、aqu-sz 与 tick 耗时叠加对照,用 perf trace -p PID --duration 10 找出游戏服务器中耗时超过 10 ms 的 write、fsync 调用及其所在线程
- 确认依据
- tick 冲高的时刻,游戏线程的 write、fsync 调用耗时几十 ms,同时磁盘写入延迟也飙升。常与日志轮转、压缩的时间重合
- 排除依据
- 游戏线程中没有耗时长的系统调用而 tick 仍冲高,是 GC、锁、tick 超出预算等其他原因。只有日志专用线程耗时长,则不影响游戏逻辑
- 确认手段
- 运维工具即可确认(无需游戏代码)
- 深入了解
- OS 通常先把写入的数据放进内存(页缓存),稍后再刷到磁盘,所以写一行日志一般会立即完成。停顿出现在这几种时候:用 fsync 要求确保落盘时;积压的写入超过上限、OS 阻塞写调用时;轮转或压缩日志文件时。所以平时一切正常,只在磁盘繁忙的瞬间冲高。
出处
- fsync(2) — Linux manual page Linux man-pages
fsync 把修改过的数据刷到磁盘(包括磁盘缓存),并阻塞到设备报告完成 - Documentation for /proc/sys/vm/ Linux kernel
积压的写入(dirty)达到 dirty_ratio 时,执行写入的进程要亲自承担刷盘工作 - ionice(1) — Linux manual page util-linux
以 idle I/O 优先级运行的任务,只在其他程序不使用磁盘时才分到磁盘时间 - iostat(1) — Linux manual page sysstat
-x:w_await(写请求的平均处理时间,包括在队列中等待的时间),aqu-sz(平均队列长度,旧名 avgqu-sz) - perf-trace(1) — Linux manual page perf
-p 跟踪运行中进程的系统调用,--duration 只显示耗时超过指定 ms 的调用
相关原因
同一层:L11 磁盘
其他层中同样导致“一卡一卡”的原因
查看含图示和实验的原卡片