- 支持 Windows Agent 构建、安装脚本和统一上报协议 - 增强 RDP 剪贴板、虚拟盘和文件传输能力 - 新增 AIOps 上下文工具、告警 RCA trace 落库和回放接口 - 重构 docs 模块文档并补充终端、堡垒机、监控、AI Agent 设计
5.7 KiB
5.7 KiB
Redis 缓存策略文档
版本: v0.43 | 最后更新: 2026-06-24
缓存总览
| 模块 | 缓存 | 方式 | Key 格式 | TTL | 说明 |
|---|---|---|---|---|---|
| Agent 指标热数据 | ✅ | Sorted Set | agent:metrics:{hostname}:{metric} |
7 天 | 聚合后批量写 MySQL |
| 流水线日志 | ✅ | pub/sub + String | pipeline:log:{runId} |
30 min | 实时推送 + 历史缓存 |
| Dashboard 统计 | ✅ | String (JSON) | dashboard:stats |
30 s | ~25 次 SQL → 1 次 Redis Get |
| 服务器列表 | ✅ | String (JSON) | servers:list:{kw}:{st}:{reg}:{p}:{ps} |
10 s | JOIN 查询 → 缓存命中 ~1ms |
| 告警中心 | ❌ | — | — | — | 表小,直接查 MySQL |
| K8s 资源 | ❌ | — | — | — | 走 K8s API,不经过 MySQL |
缓存后端
支持双后端,通过配置 driver 字段切换:
| Driver | 场景 | 依赖 |
|---|---|---|
redis |
Docker / 生产环境 | 外部 Redis 7 容器 |
redka |
二进制独立部署 | 内嵌,零依赖 |
# config.yaml
redis:
driver: redis # redis | redka
host: aiops-redis # Docker 容器名
port: 6379
password: ""
db: 0
初始化逻辑在 backend/cmd/main.go:129,如果 Redis 不可用则 cache = nil,业务自动回退到无缓存模式。
缓存接口
// pkg/redis/redis.go
type Cache interface {
Get(ctx, key) (string, error)
Set(ctx, key, value, expiration) error
Del(ctx, keys...) error
// ... ZAdd / ZRangeByScore / Publish 等
}
各缓存详解
1. Dashboard 统计 — dashboard:stats
缓存位置: handlers/dashboard.go:GetStats
变更频率: 低(统计数据,30s 延迟可接受)
Key: 全局单键 dashboard:stats
实现流程:
请求 → cache.Get("dashboard:stats")
├─ hit → json.Unmarshal → 返回(跳过 ~25 次 SQL)
└─ miss → MySQL 聚合查询 → json.Marshal → cache.Set(30s) → 返回
写入不是异步的:cache.Set 使用 context.Background(),缓存写失败不影响 HTTP 响应。
// 读缓存
if cached, err := h.cache.Get(c.Request.Context(), cacheKey); err == nil && cached != "" {
var stats models.DashboardStats
if json.Unmarshal([]byte(cached), &stats) == nil {
c.JSON(200, Response{Data: stats})
return
}
}
// ... 查询逻辑 ...
// 写缓存
if data, err := json.Marshal(stats); err == nil {
_ = h.cache.Set(context.Background(), cacheKey, string(data), 30*time.Second)
}
2. 服务器列表 — servers:list:*
缓存位置: handlers/server.go:ListServers
变更频率: 低(服务器列表相对稳定,10s TTL 足够短)
Key 格式: servers:list:{keyword}:{status}:{region_id}:{page}:{page_size}
- 按查询参数区分,不同过滤条件独立缓存
- 写操作不主动失效(TTL 10s 自动过期)
实现流程:
请求 → cache.Get("servers:list:{params}")
├─ hit → json.Unmarshal → 返回(跳过 Preload JOIN)
└─ miss → MySQL 查询 → json.Marshal → cache.Set(10s) → 返回
// 读缓存
if h.cache != nil {
if cached, err := h.cache.Get(c.Request.Context(), cacheKey); err == nil && cached != "" {
var resp models.Response
if json.Unmarshal([]byte(cached), &resp) == nil {
c.JSON(200, resp)
return
}
}
}
// ... 查询逻辑 ...
// 写缓存
if h.cache != nil {
if data, err := json.Marshal(resp); err == nil {
_ = h.cache.Set(context.Background(), cacheKey, string(data), 10*time.Second)
}
}
3. Agent 指标热数据
缓存位置: handlers/agent.go
Key 格式: agent:metrics:{hostname}:{metric} (Sorted Set)
- Agent 上报数据先写 Redis Sorted Set(速度快)
- 定时任务批量聚合后写入 MySQL(持久化)
- TTL 7 天,历史数据以 MySQL 为准
4. 流水线日志
缓存位置: handlers/ws_pipeline_log.go + handlers/pipeline.go
- 实时推送: Redis Pub/Sub,构建输出实时流式推送到前端
- 历史缓存:
pipeline:log:{runId},TTL 30 min - 超过 30 min 的日志从 MySQL 回查
容错设计
| 场景 | 行为 |
|---|---|
| Redis 不可用(启动时) | cache = nil,日志 Warn,正常启动 |
| Redis 不可用(运行时) | cache.Get() 返回 error → 走 MySQL |
| 缓存值反序列化失败 | 走 MySQL(原逻辑) |
| 缓存写失败 | 静默忽略(_ = h.cache.Set(...)) |
关键原则:缓存是加速层,不是依赖。任何缓存故障都不影响功能正确性。
缓存大小估算
| Key | 单条大小 | 数量 | 估算总量 |
|---|---|---|---|
dashboard:stats |
~3 KB | 1 | ~3 KB |
servers:list:* |
~5 KB/组合 | ~5-10(常用过滤组合) | ~50 KB |
agent:metrics:* |
~200 B/指标 | ~15 指标 × 7 主机 | ~21 KB |
pipeline:log:* |
~50 KB/运行 | ~5 并发 | ~250 KB |
| 合计 | < 500 KB |
性能对比
| 端点 | 缓存前 | 缓存命中 | 加速比 |
|---|---|---|---|
GET /dashboard/stats |
~150ms (~25 SQL) | ~1ms | ~150x |
GET /servers |
~10ms (Preload JOIN) | ~1ms | ~10x |
Handler 缓存字段一览
所有带缓存的 handler 都持有 cache ezredis.Cache 字段,由 routes.go 统一注入:
// routes.go
redisCache, _ := cache.(ezredis.Cache)
dashboardHandler := handlers.NewDashboardHandler(db, redisCache)
serverHandler := handlers.NewServerHandler(db, cfg.JWT.Secret, redisCache)
pipelineHandler := handlers.NewPipelineHandler(db, redisCache)
wsLogHandler := handlers.NewWSPipelineLogHandler(db, redisCache)
agentHandler := handlers.NewAgentHandler(db, redisCache, metricsHub)