概述 —— 这个页面做什么
服务 ▸ 会话(Redis) 在一个页面上监控已注册 Redis 节点的会话/缓存存储健康状况。它把 服务 ▸ 数据库 的叙事移植到 Redis 上,围绕两条轴线来读取:
- 容量上限+当前状态 —— 内存饱和度环形仪表(
used_memory÷ 容量上限)、客户端连接数(connected / maxclients)以及阻塞中的客户端。 - 吞吐量 —— 每秒处理的命令数(
instantaneous_ops_per_sec)、近期窗口命中率(Δhits / Δ(hits+misses))以及网络 I/O(入/出 kbps)。
可折叠的详情面板还提供内存管理时序(容量上限叠加线+逐出事件标记)与键空间/会话分析。
本页面从不直接连接 Redis。 内网的代表采集器(
scripts/infr_redis_vts_collector.cjs,每分钟运行一次的 pm2 cron)在各节点执行redis-cli INFO,并把快照写入中央 MySQL 表infr_redis_metric;应用只读取它。应用不保存任何 Redis 凭据,也不运行常驻守护进程(从而避开连接泄漏与硬编码凭据这两个陷阱)。
何时使用
- 会话存储容量 —— 发现 Redis 内存逼近上限的情况,此时会话会在压力下被逐出(丢失)。
- 缓存效率诊断 —— 通过命中率、碎片化与 slowlog 判断缓存是否发挥了作用。
- 连接饱和 —— 当
connected_clients逼近maxclients或rejected_connections上升时,在新连接被拒绝之前及早处置。 - 持久化/复制故障 —— 以徽章形式查看 RDB bgsave 失败、AOF 重写或副本链路中断。
- 会话生命周期 —— 区分过期(正常寿命)与逐出(内存压力),从而读懂会话周转量。
页面布局
顶部 KPI
| KPI | 含义 |
|---|---|
| 节点 | 在近期(30 分钟)窗口内有样本的 Redis 节点卡片 |
| 正常 / 降级 / 不可用 | up / degraded / down 节点的数量 |
| 总 ops/秒 | 各节点 instantaneous_ops_per_sec 之和 |
| 总键数 | 各节点 keyspace_keys 之和 |
节点卡片(两条轴线)
每个节点对应一张卡片。卡头显示实例名称/别名、Redis 版本与角色(master/replica);卡体承载两条轴线。
① 容量 · 剩余(左侧环形仪表) —— 中心数值为 used_pct(已用 ÷ 容量上限)。指标条:
| 指标 | 字段 | 说明 |
|---|---|---|
| 客户端 | connected_clients / maxclients |
连接数与上限;接近上限时新连接会被拒绝 |
| 阻塞中 | blocked_clients |
等待 BLPOP·BRPOP·WAIT 的客户端(0 为健康) |
② 吞吐量(右侧) —— 迷你折线图+指标条:
| 指标 | 字段 | 说明 |
|---|---|---|
| ops/秒 | instantaneous_ops_per_sec |
每秒处理的命令数 |
| 命中率 | Δhits / Δ(hits+misses) | 近期窗口的缓存命中率(样本稀疏时回退为累计值) |
| 网络 I/O | instantaneous_input_kbps + output_kbps |
每秒网络入/出流量 |
效率评分(卡片底部)
- 命中率评级 —— 优秀 ≥99% · 良好 ≥95% · 一般 ≥80%。
- **内存效率(碎片化)**评级 —— 优秀 0.95–1.4 · 良好 ~1.6 · 一般 ~2.5。
碎片化评分(
frag_score)只在used_memory不低于 64 MB 时才计算。在小实例上,固定的分配器开销会主导该比率并造成误报,因此低于该阈值时它会同时被排除在评分与状态判定之外。
会话生命周期流转条
卡片底部有一条通栏条带,绘制将过期 → 流转 → 累计已过期。左侧为当前带有 TTL 的键(keyspace_expires,即将自然过期);右侧为自启动以来已过期的键(expired_keys,即会话周转量)。填充接近 ≈100% 说明这是一个纯粹的会话存储。
详情(展开)
两个区块以折叠方式打开(masonry 布局会在高度变化时重新排布)。
- 内存管理 ——
used与容量的时序+容量上限 100% 截止线叠加+逐出事件的 crit 标记。卡片会列出容量上限(cap)、估算剩余(est_free)、总 RAM、DB 预留、OS 预留、峰值、RSS、碎片化、累计逐出/过期以及逐出策略。 - 键空间 · 会话 —— 总键数、带 TTL 的键数、逻辑 DB(db0/db1…)分布条、高亮显示的会话 DB、平均 TTL,以及 RDB/AOF/副本持久化徽章。
教学浮层(edu)
将鼠标悬停在指标旁的图标上,会打开一个专门设计的浮层,解释原因与对策(更深入的概念见 Redis 调优详解):
| 浮层 | 内容 |
|---|---|
| SLOWLOG | 慢命令累积的 7 种原因(O(N) 命令 · 大键 · 内存压力 · fork 卡顿 · Lua · 流水线 · 大批量 DEL) |
| 命中率 | keyspace 命中率的计算依据+提升方法(让工作集常驻 · 调整 TTL · 缓解缓存击穿) |
| 碎片化 | RSS / used 的健康区间(1.0–1.5)· activedefrag · 交换分区(<1.0)警告 |
| 逻辑 DB | Redis 编号 DB(0–15)的概念 · 按用途拆分 · Cluster 可移植性 |
| 过期 · 逐出 | 过期(正常寿命)与逐出(内存压力)的区别 · 如何解读 |
使用方法
- 轮询 —— 页面加载后每 30 秒轮询一次
/service/session/live以刷新 KPI 与卡片(服务端会将仪表盘缓存 20 秒)。 - 重排卡片 —— 拖动卡片按优先级排序(SortableJS;顺序保存在 localStorage 中)。
- 展开详情 —— 使用卡片上的 [展开] 打开内存管理与键空间区块。
- 通过 edu 学习 —— 悬停指标图标即可查看原因/对策浮层。
- 全屏 —— 页头 LIVE 指示器旁的全屏按钮会隐藏顶部导航并切换到仪表盘模式(按 ESC 退出)。
如果一张卡片都没有,说明尚未注册/采集到任何 Redis 节点。请在 管理 ▸ 采集器 中为
redis_vts采集器注册redis_host节点,并在代表主机上用 pm2 部署该采集器。
数据来源
只读模型 infr_redis_metric
应用把该表映射为只读的 Legacy 风格模型(App\Models\Infr\InfrRedisMetric,$timestamps=false)。这里刻意没有迁移文件 —— 采集器会用 CREATE TABLE IF NOT EXISTS 自行创建该表,因此应用侧的 Schema::create 会产生冲突。
构建器 App\Services\Redis\RedisMetricService::dashboard() 的规约:
- 以单次批量查询取出最近 30 分钟窗口(
WINDOW_MIN)的数据,然后按node_alias分组(每个节点一张卡片)。若窗口内没有样本(采集已停止),则至少取最近 180 行,以便把节点标记为stale展示出来。 - 时序按每张卡片最近 60 个点截断(
SERIES_MAX)。累计计数器(evicted/expired)通过相邻样本的差值换算为速率;遇到重置(数值下降)时速率为null。 - 仪表盘结果会缓存 20 秒(
infr:redism:dash:v1)。
-- 概念示意(实际使用 Eloquent)。批量取出近期窗口,在 PHP 中分组。
SELECT * FROM infr_redis_metric
WHERE sampled_at >= (NOW() - INTERVAL 30 MINUTE)
ORDER BY sampled_at;
采集器 —— scripts/infr_redis_vts_collector.cjs
内网中的单台代表主机以 pm2 cron 方式运行,每次执行扫描若干节点的 Redis(redis-cli -h {ip} INFO)与 nginx vts,直接写入中央 MySQL 后退出(非常驻 → 每次运行都是全新进程,不会泄漏)。配置只存在于文件顶部的 CONFIG 块中(不用环境变量,也不硬编码凭据)。
# 在代表主机上部署(每分钟扫描一次,非常驻)
npm i mysql2 # 唯一的 npm 依赖(用于写入)。redis-cli 请通过操作系统软件包安装。
pm2 start infr_redis_vts_collector.cjs --name infr-collector \
--no-autorestart --cron-restart "* * * * *"
pm2 save
实例关联(别名 / 整型外键)
写入时,采集器会在 infr_instance 中按节点别名查出 id,并直接写入 instance_id(整型)。应用主要按 metric.instance_id = infr_instance.id 关联(整型比较 —— 与排序规则无关,且走主键索引)。未注册或后期才注册的实例会回退到 node_alias(转小写)→ infr_instance.alias,随后由 infr:link-metrics 回填任务(leader 门控,每 5 分钟一次)补上 instance_id。
容量上限(cap)的计算
环形仪表与内存图表的 100% 基准按以下顺序确定。
| cap 类型 | 条件 | 上限 | 估算剩余(est_free) |
|---|---|---|---|
maxmemory |
maxmemory > 0 |
maxmemory 设置值(硬上限) | maxmemory − used |
budget |
未设置 maxmemory | 总 RAM − DB 缓冲池 − OS 预留 | budget − used |
- 总 RAM =
total_system_memory(采集值),取不到时回退为infr_instance.mem_mb。 - OS 预留 = 总 RAM ×
redis_reserve_pct(默认 20%)。 - DB 缓冲池 = 同一节点上最新的
access=database采集器的infr_db_metric.raw.bp_size(若一个节点承载多个数据库则求和)。扣除它之后,得到的就是 Redis 实际可用的预算,并以此作为上限。 - 该预算设有下限,绝不会低于当前的
used,从而避免出现负值或倒挂。
状态判定与阈值
statusOf() 把每个节点归类为 up / degraded / down。
| 状态 | 条件 |
|---|---|
down |
采集失败(ok=0)或 stale(最后一次样本早于 redis_stale_min) |
degraded |
命中下列原因中的一项或多项 |
up |
没有任何原因 |
degraded 的原因与阈值(管理 ▸ 运维策略,infr_setting group=ops):
| 原因 | 条件 | 阈值键 | 默认值 |
|---|---|---|---|
| 内存饱和 | used_pct ≥ |
redis_mem_pct |
85 |
| 碎片化 | frag_score ≥ |
redis_frag_ratio |
1.6 |
| 阻塞中的客户端 | blocked_clients ≥ |
redis_blocked |
1 |
| 副本链路中断 | master_link_status = down |
— | — |
| RDB 保存失败 | rdb_last_bgsave_status = err |
— | — |
命中率不是状态判定轴。 会话存储在每一次新登录、过期和登出时都会未命中,因此 40–60% 的命中率是正常的(例如一个完全健康的会话节点为 44.75%)。早前,低于
redis_hit_rate_min(默认 50)的命中率会产生误报的红色degraded;现在命中率只在卡片 KPI、评级仪表和 edu 浮层中展示,绝不会把节点标红。真正的缓存问题(内存饱和、逐出、碎片化)无论工作负载如何,都会由mem_saturation/fragmentation捕获。
访问权限
- 查看(本页面) ——
user_level ≥ 1(demo=1)。服务角色区域的最低等级为 1,且本页面为只读(没有写入/删除操作)。 - 采集器注册/编辑 —— 在 管理 ▸ 采集器 中为
redis_vts采集器注册redis_host节点及密码,需要user_level ≥ 5(staff/admin)。 - 修改阈值 —— 管理 ▸ 运维策略 需要
user_level ≥ 5。
本页面没有破坏性操作,因此不会写入自己的审计日志(采集器与策略的变更会在各自的管理页面上被审计)。
故障排查与常见问题
一张卡片也没有(“未采集到 Redis 节点”)
infr_redis_metric 中没有近期样本。请检查:(1) 是否已在 管理 ▸ 采集器 中为 redis_vts 采集器注册了 redis_host 节点;(2) 代表主机上的 infr_redis_vts_collector.cjs 是否在 pm2 下运行;(3) 代表主机能否通过 redis-cli 访问各节点的 Redis 端口。
某个节点显示“不可用(stale)”
最后一次样本早于 redis_stale_min(默认 5 分钟)。多半是代表采集器的 pm2 进程已死或其 cron 已停止。可用 pm2 list / pm2 logs infr-collector 排查。
环形仪表的上限看起来不对/剩余空间显得过大
没有设置 maxmemory 的节点会以预算作为上限(总 RAM − DB 缓冲池 − 20% OS 预留)。若需要硬上限,请在 Redis 上设置 maxmemory —— 该值随后会直接成为上限。
键空间/会话区块是空的
按 DB 的明细(raw.keyspace)与会话 DB 指标由扩展后的采集器填充。若使用的是旧版采集器,请重新部署(会幂等地补上 total_system_memory、keyspace_keys 以及按 DB 的 raw 列),该区块随即出现。若未采集到,该区块会优雅地隐藏。
命中率偏低 —— 这是问题吗?
对于会话型负载,不是问题(见上面的警告)。如果它是纯缓存而命中率偏低,可能是工作集未常驻或 TTL 设得太短 —— 参见 Redis 调优详解 中的命中率主题。
没有显示碎片化评分
当 used_memory 低于 64 MB 时,碎片化比率会被固定开销主导而失去意义,因此会被排除在评分与状态判定之外。
相关内容
- 数据库(服务 ▸ 数据库) —— 为 MySQL 实现同一套叙事(容量 · 吞吐量 · 结构)的姊妹页面
- Redis 调优详解 —— 关于 slowlog、命中率、碎片化、键空间与逐出的深入讲解
- 采集器(管理 ▸ 采集器) —— 注册
redis_vts采集器及其节点 - 运维策略(管理 ▸ 运维策略) —— 设置 Redis 状态阈值与预留比例
- 服务概览(服务 ▸ 概览) —— 把会话卡片固定到优先级看板上
