한국어English日本語简体中文繁體中文DeutschไทยTiếng ViệtРусскийPortuguês (Brasil)EspañolBahasa Indonesia

游戏卡顿白皮书 › L12 数据库

Redis 慢命令 Redis blocking commands (single-threaded)

原因 ID db-redis-block · 主责 研发团队·服务器开发 · 配合 运维团队·数据库运维

在含图示和实验的完整版中打开此卡片 →

Redis 一次只处理一条命令,一条慢命令就会挡住后面所有请求。

起因 运营中用 KEYS 全量搜索,整体读取或删除含几百万元素的排行榜、列表 → 结果 这条命令结束前,其他所有请求都在等待(几十 ms 到几秒) → 画面表现 用到会话、排行榜、缓存的功能同时顿一下,登录变慢

症状
卡住, 操作延迟, 连不上/无限加载
因素
停顿, 延迟
谁会遇到
全服, 仅特定功能
何时出现
偶尔随机, 固定周期
负责方
主责 研发团队·服务器开发 · 配合 运维团队·数据库运维
研发团队要做的事
用 SCAN 代替 KEYS,拆分大 key,删除用 UNLINK(后台删除),打散集中在同一秒的过期时间。
运维团队要做的事
监控慢命令日志(SLOWLOG),在生产服务器上禁用 KEYS 等危险命令,定期排查大 key,关闭 THP 并为 fork 预留内存,RDB、AOF 持久化放到从节点上做。
数值参考
普通命令不到 1 ms。一次处理几百万个元素时,可能要几百 ms 甚至几秒。
监控图上
偶发随机尖峰 · Redis 响应延迟、慢命令数
查看位置
用 SLOWLOG GET 查看超过 slowlog-log-slower-than 的命令;用 CONFIG SET latency-monitor-threshold 开启延迟监控(默认关闭)后,用 LATENCY LATEST、LATENCY DOCTOR 查看 fork、expire-cycle 等各类事件的延迟。再用 INFO 的 latest_fork_usec 和 redis-cli --bigkeys 确认 fork 耗时和大 key
确认依据
停顿时刻的 SLOWLOG 中有 KEYS 或整体操作大 key 的命令,或者 LATENCY 在同一时刻记录了几十 ms 以上的 fork、expire-cycle 事件
排除依据
SLOWLOG、LATENCY 都是空的,只有游戏服务器侧感觉慢,属于网络或游戏服务器内部的等待(SLOWLOG 只统计命令执行时间,不含与客户端之间的收发时间)
确认手段
运维工具即可确认(无需游戏代码)
深入了解
为了生成持久化文件(RDB 快照)或重写 AOF 而复制进程(fork)的瞬间,Redis 也会停顿。在现在的服务器上大约每 1 GB 内存需要 10 ms,30 GB 就是 300 ms 左右。开启大页(THP)时,fork 之后每次写入都要整页复制大页(copy-on-write),停顿和内存占用都会大幅增加,所以通常会关闭 THP 并预留充足内存。同一秒内过期的键非常多时,Redis 也会因为忙着删除而短暂停顿。

出处

  1. Diagnosing latency issues Redis
    由一个线程依次处理请求,慢命令会挡住后面所有请求;用 SCAN 代替 KEYS;fork 在物理机和新型虚拟机上实测每 1 GB 约 9~13 ms;THP 会因 fork 之后的复制导致延迟和内存激增;同一秒内大量键过期会造成停顿
  2. KEYS Redis
    在生产环境中要极其谨慎地使用,在大数据库上可能严重拖垮性能(入门级笔记本上 100 万个键需要 40 ms)
  3. UNLINK Redis
    异步删除:立即把键从键空间中摘除,内存回收交给其他线程完成
  4. SLOWLOG Redis
    记录超过 slowlog-log-slower-than 的命令的慢命令日志;执行时间不包括与客户端之间的 I/O
  5. Redis latency monitoring Redis
    latency-monitor-threshold 默认为 0(关闭),LATENCY LATEST、LATENCY DOCTOR,按 fork、expire-cycle 等事件记录延迟
  6. INFO Redis
    latest_fork_usec:最近一次 fork 所用的时间(微秒)
  7. Redis CLI Redis
    --bigkeys:扫描键空间,找出大 key

相关原因

同一层:L12 数据库

其他层中同样导致“卡住”的原因

查看含图示和实验的原卡片