Files
aiops/docs/platform/redis-caching-strategy.md
T
Logan.Li e0d652d211 feat: 完善堡垒机与 Agent 智能运维能力
- 支持 Windows Agent 构建、安装脚本和统一上报协议

- 增强 RDP 剪贴板、虚拟盘和文件传输能力

- 新增 AIOps 上下文工具、告警 RCA trace 落库和回放接口

- 重构 docs 模块文档并补充终端、堡垒机、监控、AI Agent 设计
2026-07-05 23:49:36 +08:00

5.7 KiB
Raw Blame History

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)