lawless/docs/ai-collab/T038-缓存池实现.md
2026-07-02 17:27:06 +08:00

6.7 KiB

T038 缓存池实现

审查AgentMiMo 日期2026-07-03 审查范围Redis/Valkey缓存系统设计


一、缓存系统架构

1.1 缓存层级

┌─────────────────────────────────────┐
│           应用层缓存                 │
│    (Go进程内缓存, TTL短)            │
├─────────────────────────────────────┤
│           Redis/Valkey缓存          │
│    (分布式缓存, TTL中)              │
├─────────────────────────────────────┤
│           PostgreSQL数据库           │
│    (持久化存储, 查询慢)             │
└─────────────────────────────────────┘

1.2 缓存策略

数据类型 缓存位置 TTL 更新策略
角色信息 Redis 5分钟 写时失效
会话数据 Redis 30分钟 写时失效
配置数据 Redis 1小时 定时刷新
战斗数据 Redis 10分钟 写时失效
排行榜 Redis 1分钟 实时更新

二、缓存Key设计

2.1 Key命名规范

{模块}:{类型}:{ID}

2.2 Key列表

模块 Key格式 TTL 说明
角色 char:{id} 5min 角色基本信息
角色属性 char:{id}:stats 5min 角色战斗属性
会话 session:{id} 30min 玩家会话数据
功法 manual:{char_id}:{id} 5min 功法实例数据
技能 skill:{char_id}:{id} 5min 技能实例数据
货币 currency:{char_id} 5min 货币余额
排行榜 rank:{type}:{tier} 1min 各类排行榜
战斗 battle:{id} 10min 战斗记录
配置 config:{key} 1hour 配置数据

三、缓存操作封装

3.1 基础操作

// 缓存操作接口
type CacheInterface interface {
    Get(key string) (string, error)
    Set(key string, value string, ttl time.Duration) error
    Del(key string) error
    Exists(key string) (bool, error)
    Incr(key string) (int64, error)
    Expire(key string, ttl time.Duration) error
}

// Redis实现
type RedisCache struct {
    client *redis.Client
}

func (c *RedisCache) Get(key string) (string, error) {
    return c.client.Get(ctx, key).Result()
}

func (c *RedisCache) Set(key string, value string, ttl time.Duration) error {
    return c.client.Set(ctx, key, value, ttl).Err()
}

func (c *RedisCache) Del(key string) error {
    return c.client.Del(ctx, key).Err()
}

3.2 业务封装

// 角色缓存
func GetCharacterCache(charID string) (*Character, error) {
    key := "char:" + charID
    data, err := cache.Get(key)
    if err != nil {
        // 缓存未命中,从数据库加载
        char, err := loadCharacterFromDB(charID)
        if err != nil {
            return nil, err
        }
        // 写入缓存
        cache.Set(key, json.Marshal(char), 5*time.Minute)
        return char, nil
    }
    var char Character
    json.Unmarshal([]byte(data), &char)
    return &char, nil
}

func SetCharacterCache(charID string, char *Character) error {
    key := "char:" + charID
    data, _ := json.Marshal(char)
    return cache.Set(key, string(data), 5*time.Minute)
}

func InvalidateCharacterCache(charID string) error {
    keys := []string{
        "char:" + charID,
        "char:" + charID + ":stats",
        "currency:" + charID,
    }
    return cache.Del(keys...)
}

四、缓存一致性

4.1 写时失效策略

当数据更新时,立即失效相关缓存:

func UpdateCharacter(charID string, data map[string]interface{}) error {
    // 1. 更新数据库
    err := updateDB(charID, data)
    if err != nil {
        return err
    }
    
    // 2. 失效缓存
    InvalidateCharacterCache(charID)
    
    return nil
}

4.2 缓存穿透防护

// 防止缓存穿透:查询不存在的数据时,缓存空值
func GetWithProtection(key string) (string, error) {
    data, err := cache.Get(key)
    if err == redis.Nil {
        // 缓存未命中
        data, err := loadFromDB(key)
        if err != nil {
            // 数据不存在,缓存空值短TTL
            cache.Set(key, "", 1*time.Minute)
            return "", nil
        }
        cache.Set(key, data, 5*time.Minute)
        return data, nil
    }
    return data, err
}

五、缓存监控

5.1 监控指标

指标 说明 告警阈值
命中率 缓存命中/总请求 <80%
内存使用 Redis内存使用量 >80%
连接数 Redis连接数 >1000
延迟 缓存操作延迟 >10ms

5.2 监控命令

# 查看Redis状态
redis-cli info memory

# 查看命中率
redis-cli info stats | grep keyspace_hits

# 查看连接数
redis-cli info clients

六、缓存预热

6.1 启动预热

func WarmupCache() {
    // 预热配置数据
    loadConfigCache()
    
    // 预热排行榜
    loadRankCache()
    
    // 预热热门角色
    loadHotCharacters()
}

6.2 定时刷新

// 定时刷新配置缓存
go func() {
    ticker := time.NewTicker(1 * time.Hour)
    for range ticker.C {
        loadConfigCache()
    }
}()

七、缓存配置

7.1 Redis配置

redis:
  addr: "localhost:6379"
  password: ""
  db: 0
  pool_size: 10
  min_idle_conns: 5
  max_retries: 3
  retry_delay: 100ms

7.2 缓存配置

cache:
  character_ttl: 5m
  session_ttl: 30m
  config_ttl: 1h
  battle_ttl: 10m
  rank_ttl: 1m
  max_memory: 1gb
  eviction_policy: allkeys-lru

八、性能优化

8.1 批量操作

// 批量获取
func GetMulti(keys []string) (map[string]string, error) {
    return cache.MGet(keys...)
}

// 批量设置
func SetMulti(data map[string]string, ttl time.Duration) error {
    pipe := cache.Pipeline()
    for k, v := range data {
        pipe.Set(ctx, k, v, ttl)
    }
    _, err := pipe.Exec(ctx)
    return err
}

8.2 本地缓存

// 使用Go自带的sync.Map作为L1缓存
var localCache sync.Map

func GetWithLocalCache(key string) (string, error) {
    // L1: 本地缓存
    if val, ok := localCache.Load(key); ok {
        return val.(string), nil
    }
    
    // L2: Redis缓存
    data, err := cache.Get(key)
    if err != nil {
        return "", err
    }
    
    // 写入L1缓存短TTL
    localCache.Store(key, data)
    go func() {
        time.Sleep(30 * time.Second)
        localCache.Delete(key)
    }()
    
    return data, nil
}

缓存池实现 v1.0 | 2026-07-03 | T038