Redis 缓存策略

2026-06-22 · 6 阅读 · 322字
性能优化数据库

Redis 缓存策略

缓存模式

Cache Aside(旁路缓存)

应用程序同时维护缓存和数据库:

读:先查缓存 → 命中则返回 → 未命中则查 DB → 写入缓存 → 返回
写:先更新 DB → 使缓存失效
func GetUser(id string) (*User, error) {
    // 1. 查缓存
    user, err := cache.Get("user:" + id)
    if err == nil {
        return user, nil
    }

    // 2. 缓存未命中,查数据库
    user, err = db.GetUser(id)
    if err != nil {
        return nil, err
    }

    // 3. 写入缓存(设置过期时间)
    cache.Set("user:"+id, user, 1*time.Hour)
    return user, nil
}

func UpdateUser(id string, data *User) error {
    // 1. 更新数据库
    err := db.UpdateUser(id, data)
    if err != nil {
        return err
    }

    // 2. 使缓存失效
    cache.Del("user:" + id)
    return nil
}

Read Through

缓存层负责从数据库加载数据,应用程序只与缓存交互。

Write Through

写入时先写缓存,缓存负责同步写入数据库。

Write Behind

写入时只写缓存,缓存异步批量写入数据库,性能最好但可能丢数据。

常见问题

缓存穿透

查询一个不存在的数据,导致每次请求都穿透到数据库。

解决方案

// 1. 缓存空值
cache.Set("user:no_such_id", nil, 5*time.Minute)

// 2. 布隆过滤器
bloomFilter.Contains("user:no_such_id") // 快速判断不存在

缓存雪崩

大量缓存同时过期,导致请求全部落到数据库。

解决方案

// 1. 过期时间加随机值
expire := 3600 + rand.Intn(600) // 基础时间 + 随机值

// 2. 多级缓存:本地缓存 + Redis
// 3. 限流降级:保护数据库

缓存击穿

热点 key 在过期瞬间被大量并发请求穿透。

解决方案

// 互斥锁(分布式锁)
func GetUserWithLock(id string) (*User, error) {
    // 1. 查缓存
    user, _ := cache.Get("user:" + id)
    if user != nil {
        return user, nil
    }

    // 2. 获取分布式锁
    lock := redisLock.Lock("lock:user:" + id)
    if !lock {
        // 没拿到锁,等待后重试
        time.Sleep(50 * time.Millisecond)
        return GetUserWithLock(id)
    }
    defer lock.Unlock()

    // 3. 双重检查
    user, _ = cache.Get("user:" + id)
    if user != nil {
        return user, nil
    }

    // 4. 查数据库
    user, _ = db.GetUser(id)
    cache.Set("user:"+id, user, 1*time.Hour)
    return user, nil
}

缓存与数据库一致性问题

最终一致性方案

  1. 先更新 DB,后删缓存(推荐)
  2. 配合消息队列,异步重试失败的缓存删除
  3. 设置合理的过期时间兜底

内存淘汰策略

策略 说明 适用场景
noeviction 不淘汰,写满返回错误 不允许丢数据
allkeys-lru 淘汰最近最少使用的 key 通用缓存
allkeys-lfu 淘汰最不经常使用的 key 访问频率差异大
volatile-ttl 淘汰即将过期的 key 设置了过期时间的缓存
volatile-lru 在设置了过期时间的 key 中 LRU 混合场景
# 配置最大内存和淘汰策略
maxmemory 4gb
maxmemory-policy allkeys-lru