InfraGuard

Redis 调优概念(会话教学)

如何解读 服务 ▸ 会话 (Redis) 页面上的 Redis 指标 —— slowlog 的 7 种成因、命中率、内存碎片化健康区间,以及过期与逐出的区别。

概述 —— 本页讲什么

本文讲解如何 解读并处置 您在 服务 ▸ 会话 (Redis) 页面(/service/session)上看到的指标。那个页面是实时监控控制台;本页解释其背后的 Redis 运维概念 —— slowlog、键空间命中率、内存碎片化,以及过期与逐出。

InfraGuard 从不直接连接 Redis。 内网代表采集器(scripts/infr_redis_vts_collector.cjs,以 pm2 每分钟 cron 方式运行)从各节点抓取一次 redis-cli INFO 快照,并写入中央 MySQL 表 infr_redis_metric;应用只 读取 该表。因此这里的每一个数值都来自标准的 INFO 字段。

每项指标的 确切术语与改进建议 以单一来源存放在会话页面的 教学浮层(悬停显示) 中(resources/lang/{ko,en}/redis.php 的 edu.*)。本文是对这些概念的归纳与串联,而非重新定义 —— 完整细节请悬停查看实时浮层。

何时使用

页面布局

一张会话卡片代表一个节点(node_alias = infr_instance.alias,1:1),并沿用 服务 ▸ 数据库 的叙事方式。

区域 展示内容 来源 INFO 字段
① 容量 · 空闲 内存容量环(已用 / 上限)· 客户端(已连接/最大)· 阻塞中 used_memory, maxmemory, total_system_memory, connected_clients, maxclients, blocked_clients
② 吞吐 ops/s 迷你图 · 近期窗口命中率 · 网络 I/O instantaneous_ops_per_sec, keyspace_hits/misses, instantaneous_input/output_kbps
底部效率 命中率评级 · 内存(碎片化)评级 hit_rate, mem_fragmentation_ratio
会话生命周期流 待过期(带 TTL)→ 流向 → 累计过期 keyspace_expires, expired_keys
详情(可折叠) 内存管理时间序列 + 容量上限叠加线 + 逐出事件标记 · 键空间/会话分析 used_memory 序列, evicted_keys, INFO keyspace

顶部 KPI:节点数 · 正常/降级/不可用 · 总 ops/s · 总键数 · 客户端合计。

容量(上限)如何确定

环形仪表与内存图表的 100% 基准(预算)按以下顺序选取:

  1. 若已设置 maxmemory,它就是硬上限(由 Redis 强制执行)。估算空闲 = maxmemory − used。
  2. 若未设置(无限制),预算 = total RAM − DB buffer pool − OS/other reserve (%)。预留默认为 20%(运维策略 redis_reserve_pct);数据库缓冲池取自同一节点的 access=database 采集器并从中扣除。

maxmemory 0(无限制)的节点会显示“maxmemory 未设置 —— 按操作系统/服务器内存相对显示”的提示。对于专用的会话实例,请设置一个明确的 maxmemory(取操作系统内存的一部分),使逐出策略的行为可预期。

使用方法

1) slowlog —— 它为何增长(7 种成因归纳)

Redis 是 单线程 的,因此一条慢命令会阻塞整台服务器。slowlog_len 是超过 slowlog-log-slower-than(默认 10ms)的命令累计计数。按常见程度排序:

  1. O(N) 命令 —— KEYS *、SMEMBERS、HGETALL、LRANGE 0 -1 会扫描整个集合。首要成因。
  2. 大键操作 —— 数 MB 的 String,或大型 Hash/Set/ZSet 的序列化 + 传输开销。
  3. 内存压力 / 交换 —— 已用量接近上限时,内存分配开始停顿。
  4. 持久化 fork 延迟 —— RDB bgsave / AOF 重写的 latest_fork_usec。
  5. 繁重的 Lua/函数脚本 —— 繁重的 EVAL 在执行期间持续阻塞。
  6. 大批量流水线 / MULTI —— 一次性数千条命令会让其余命令排队等待。
  7. 删除大键的 DEL —— 请用异步的 UNLINK 代替 DEL。

直接在节点上确认究竟触发了哪些命令:

# 最近 10 条慢命令(redis-cli)
redis-cli SLOWLOG GET 10
# 阈值 + 保留条数(微秒 · 例如 10ms)
redis-cli CONFIG SET slowlog-log-slower-than 10000
redis-cli CONFIG SET slowlog-max-len 128
redis-cli SLOWLOG RESET

切勿在生产环境执行 KEYS * —— 在它扫描整个键空间期间,其他所有命令都会等待。请改用游标迭代器 SCAN / HSCAN / SSCAN / ZSCAN。

2) 键空间命中率 —— 低并不等于缺陷

近期窗口命中率 = Δkeyspace_hits / (Δhits + Δmisses)。当样本过少(差值分母 < 20)时,回退到自启动以来的 hit_rate。评级:优秀 ≥99% · 良好 ≥95% · 一般 ≥80%。

命中率并不是会把节点标红的状态维度。 会话存储天生命中率就低 —— 每次新登录、过期和登出都是一次未命中,因此 40–60% 属于正常(例如 blue 的 44.75% 就是一个完全健康的会话节点)。正因如此,尽管存在 redis_hit_rate_min 阈值(默认 50),它 并不用于状态判定 —— 仅用于解读参考。真正的缓存问题,由下文与工作负载无关的内存饱和 / 逐出 / 碎片化来捕捉。

要真正提升命中率:让工作集常驻内存(预留 RAM/maxmemory 余量)、把 TTL 调到合适大小、缓解缓存击穿(给 TTL 加抖动),并对未命中较多的前缀做预热。详情请查看实时命中率浮层。

3) 内存碎片化 —— 健康区间 1.0 到 1.5

mem_fragmentation_ratio = used_memory_rss / used_memory —— 操作系统给 Redis 的物理内存与 Redis 实际使用量之比。

比率 含义 处置
1.0 – 1.5 健康区间 正常
> 1.5 已碎片化(浪费内存) activedefrag yes(需要 jemalloc),减少大值的频繁创建/删除
< 1.0 正在交换(危险) 立即 增加内存或调低 maxmemory 以停止交换 —— 这是性能骤降的信号

评级:优秀 0.95–1.4 · 良好 ~1.6 · 一般 ~2.5。状态阈值 redis_frag_ratio 默认为 1.6。

在 used_memory 低于 64MB 的小实例上,固定开销会主导该比率,碎片化数值就成了误报。此时 InfraGuard 会 将碎片化排除在评分之外(frag_score = null)—— 数值仍会显示,但不会把节点标红。

4) 过期与逐出 —— 会话生命周期的核心

术语 含义 信号
过期(expired_keys) TTL 到期后的自然移除 = 正常的会话生命周期 新陈代谢 · 通常正常
逐出(evicted_keys) 达到 maxmemory 后按策略强制移除 内存压力 · 有会话丢失风险

在会话存储中,过期是正常的,但 逐出持续大于 0 意味着正在丢弃活跃会话。应对方式:

# 查看 / 修改逐出策略
redis-cli CONFIG GET maxmemory-policy
redis-cli CONFIG SET maxmemory-policy volatile-lru
# 在线碎片整理(用于碎片化 > 1.5 · 需要 jemalloc)
redis-cli CONFIG SET activedefrag yes

详情中的 内存管理图表 会在 used_pct 上叠加一条 100% 容量上限线,并用 crit 标记标出 逐出事件 —— 于是您可以直观地追溯节点何时触顶并丢弃了会话。

5) 解读逻辑库(keyspace)

INFO keyspace 报告各个编号且彼此独立的键空间(逻辑库,默认 16 个,索引 0–15)的键数量。

# INFO keyspace example
db0:keys=48213,expires=48213,avg_ttl=1680000
db1:keys=126,expires=0,avg_ttl=0

键数最多的库就是主会话存储;如果该库的 keys = expires(全部带 TTL),那它就是纯粹的会话存储(键会自然失效)。在上例中,db0 可读作会话(全部带 TTL),db1 则是另一种用途(缓存/锁)。

数据来源

项目 值
来源表 infr_redis_metric(中央 MySQL · 只读读取模型,$timestamps=false)
供数采集器 scripts/infr_redis_vts_collector.cjs(pm2,每分钟)—— redis-cli INFO
建表方式 采集器通过 CREATE TABLE IF NOT EXISTS 自建(无迁移)
关联键 instance_id(整数外键优先)→ 回退到 node_alias ↔ infr_instance.alias
构建器 App\Services\Redis\RedisMetricService(单次批量查询 · 20 秒缓存)
近期窗口 30 分钟(WINDOW_MIN)· 图表最多 60 个点 · 30 秒轮询(/service/session/live)
阈值 SOT App\Support\OpsPolicy::redisThresholds()

状态阈值(运维策略 infr_setting group=ops):

键 默认值 判定
redis_mem_pct 85 容量(%) ≥ → 降级(mem_saturation)
redis_frag_ratio 1.6 碎片化 ≥ → 降级(fragmentation,仅当 used ≥ 64MB 时)
redis_blocked 1 阻塞客户端数 ≥ → 降级(blocked_clients)
redis_stale_min 5 最后一次采样早于 N 分钟 → 不可用(stale)
redis_hit_rate_min 50 仅供显示/解读(不用于状态判定)
redis_reserve_pct 20 估算空闲时使用的操作系统/其他预留(%)

master_link_status=down(副本链路断开)与 rdb_last_bgsave_status=err(RDB 保存失败)同样会被判定为降级原因。分库的 keyspace 详情、total_system_memory 以及键总数属于采集器扩展列 —— 在较旧的采集器上,这些区块会优雅地隐藏(“采集器重新部署后显示”)。

访问权限

疑难解答与常见问题

Q. 页面只显示“尚未采集到 Redis 节点”。 A. infr_redis_metric 为空。请在 管理 ▸ 采集器 中为 redis_vts 采集器注册 redis_host 节点,并在代表主机上以 pm2 部署 scripts/infr_redis_vts_collector.cjs。采集器会通过 CREATE TABLE IF NOT EXISTS 建表,并每分钟采集一次。

Q. 某节点一直处于不可用,原因是 stale。 A. 最后一次采样已早于 5 分钟(redis_stale_min)—— 可能是 pm2 采集器已停止(pm2 ls),或到该节点的网络/redis-cli 访问被阻断。请检查采集器日志。

Q. 键空间/会话分析与内存上限区块不见了。 A. total_system_memory、分库 keyspace 以及键总数列属于采集器扩展。在较旧的采集器上它们为 null,因此这些区块会隐藏 —— 重新部署最新采集器即可显示。

Q. 命中率只有 45%,为什么没有判定为降级? A. 这是设计使然。会话存储通常命中率就低,因此命中率永远不会把节点标记为降级。真正的问题(内存饱和、逐出、碎片化)由其他维度捕捉。

Q. 碎片化显示 3.0,但实例非常小。 A. 当 used_memory 低于 64MB 时,固定开销会扭曲该比率。此时 InfraGuard 会将碎片化排除在评分之外 —— 请把该数值当作参考信息。只要不是真正在交换(<1.0),基本无需担心。

相关内容

세션 화면의 튜닝 교육 패널
세션 화면의 튜닝 교육 패널