游戏卡顿白皮书 › L12 数据库
冷缓存(刚重启时) Cold buffer pool after restart
原因 ID db-cold-cache · 主责 运维团队·数据库运维 · 配合 研发团队·服务器开发
在含图示和实验的完整版中打开此卡片 →
DB 重启后内存缓存是空的,一段时间内所有查询都要从磁盘读取。
起因 维护时重启 DB → 结果 常用数据不在内存里,只能从磁盘读 → 画面表现 维护结束后一段时间内登录、加载很慢
- 症状
- 连不上/无限加载, 操作延迟
- 因素
- 延迟
- 谁会遇到
- 全服
- 何时出现
- 刚登录/维护结束后
- 负责方
- 主责 运维团队·数据库运维 · 配合 研发团队·服务器开发
- 研发团队要做的事
- 分批开服(用登录排队逐步放开登录人数)。
- 运维团队要做的事
- 重启后预热缓存(确认缓冲池的保存、恢复设置),从快照恢复的 DB 还要预读磁盘。
- 监控图上
- 开服/维护后激增 · 磁盘读取、缓冲区缓存命中率
- 查看位置
- MySQL 看 Innodb_buffer_pool_reads(缓冲池中没有、从磁盘读取的次数)与 Innodb_buffer_pool_read_requests 的比值,以及预热进度 Innodb_buffer_pool_load_status。PostgreSQL 看 pg_stat_database 的 blks_read、blks_hit。同时看 DB 服务器的磁盘读取次数
- 确认依据
- 重启后磁盘读取飙升、命中率偏低,随时间推移逐渐恢复,这段时间登录、加载很慢
- 排除依据
- 命中率和平时一样,维护结束后仍然慢,看“登录激增与 N+1 查询”(db-login-storm)或“连接池耗尽”(db-pool)
- 确认手段
- 运维工具即可确认(无需游戏代码)
- 深入了解
- MySQL 关闭时会保存缓冲池的页列表,启动时在后台重新读入,但填满需要时间。在云上用快照(磁盘副本)恢复的 DB,磁盘本身每个块第一次读取时也很慢,持续时间会更长。
- 真实案例
- Roblox 2021: Roblox 73 小时故障:服务发现(Consul)集群的争用问题
出处
- Saving and Restoring the Buffer Pool State MySQL
为缩短重启后的预热时间,关闭时保存最近使用的页列表(默认 25%),启动时重新读入;两项默认都已开启 - pg_prewarm — preload relation data into buffer caches PostgreSQL
定期记录共享缓冲区的内容,重启后重新载入(autoprewarm) - Initialize Amazon EBS volumes AWS
由快照创建的卷,在所有块拉取完成之前延迟增加、性能下降 - Server Status Variables MySQL
Innodb_buffer_pool_reads(缓冲池中没有、只能直接从磁盘读取的逻辑读次数),Innodb_buffer_pool_read_requests,Innodb_buffer_pool_load_status(预热进度) - The Cumulative Statistics System (PostgreSQL Documentation) PostgreSQL
pg_stat_database 的 blks_read(从磁盘读取的块数)、blks_hit(在缓冲区缓存中命中的块数)
相关原因
同一层:L12 数据库
其他层中同样导致“连不上/无限加载”的原因
查看含图示和实验的原卡片