跳到主要内容

T038 缓存池实现

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


一、缓存系统架构

1.1 缓存层级

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

1.2 缓存策略

数据类型缓存位置TTL更新策略
角色信息Redis5分钟写时失效
会话数据Redis30分钟写时失效
配置数据Redis1小时定时刷新
战斗数据Redis10分钟写时失效
排行榜Redis1分钟实时更新

二、缓存Key设计

2.1 Key命名规范

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

2.2 Key列表

模块Key格式TTL说明
角色char:{id}5min角色基本信息
角色属性char:{id}:stats5min角色战斗属性
会话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