# Redis Cache Patterns

> 后端 Redis 缓存设计规范与最佳实践。当用户需要实现缓存逻辑、处理高并发读取、防止缓存击穿/穿透/雪崩，或设计分布式锁时使用此 skill。

- Skill: `migoxlab/redis-cache-patterns` (Agent Skill)
- Install (CLI): `npx skillmds@latest add migoxlab/redis-cache-patterns`
- Raw SKILL.md: https://api.skillmd.com/api/skills/migoxlab/redis-cache-patterns/raw
- Safety review: pending (external: skill-scanner PASS, skillspector PASS)
- Works with: Claude Code, Claude.ai, OpenAI Codex
- Category: Coding & Dev Tools
- Author: migoxlab (https://skillmd.com/u/migoxlab)
- Updated: 2026-09-21
- Page: https://skillmd.com/skills/migoxlab/redis-cache-patterns

---


# Redis 缓存最佳实践 Skill

## 描述

这个 skill 帮助开发者在后端服务中正确、高效、安全地使用 Redis。涵盖了缓存键命名规范、缓存更新策略、高并发下的三大缓存问题（穿透、击穿、雪崩）的解决方案，以及分布式锁的正确实现。

## 何时使用

在以下场景中使用这个 skill：
- AI 协助编写涉及 Redis 读写操作的代码时
- 用户需要优化高并发查询接口时
- 用户询问如何解决缓存穿透、击穿、雪崩时
- 需要实现分布式锁或限流功能时

## 核心设计原则

### 1. Key 命名规范

规范的 Key 命名有助于排查问题和管理内存。

- **格式**：`业务线:子模块:实体类型:实体ID`
- **分隔符**：统一使用冒号 `:` 分隔。
- **示例**：
  - ✅ `user:profile:info:12345`
  - ✅ `order:payment:status:ORD999`
- **长度控制**：Key 不宜过长，尽量控制在 64 字节以内，避免占用过多内存。

### 2. 缓存更新策略 (Cache Update Patterns)

推荐使用 **Cache Aside Pattern (旁路缓存模式)**：

**读操作**：
1. 先读缓存，命中则直接返回。
2. 未命中，则读数据库。
3. 将数据库读到的数据写入缓存，并设置过期时间。

**写操作**：
1. 先更新数据库。
2. **再删除缓存**（注意是删除，不是更新）。

*为什么是删除而不是更新？*
并发写时，更新缓存容易导致脏数据；删除缓存操作简单，且下次读取时会自动加载最新数据（延迟计算）。

### 3. 高并发缓存三大问题及解决方案

#### 缓存穿透 (Cache Penetration)
**定义**：查询一个**根本不存在**的数据，缓存层和数据库层都不会命中，导致请求全部打到数据库。
**解决方案**：
1. **缓存空对象**：即使数据库返回空，也将其缓存起来（如缓存一个特殊的标识 `"{}"`），并设置较短的过期时间（如 30 秒）。
2. **布隆过滤器 (Bloom Filter)**：在缓存层前加一层布隆过滤器，快速判断数据是否存在。

#### 缓存击穿 (Cache Breakdown)
**定义**：一个**热点 Key** 在失效的瞬间，海量并发请求同时打到数据库，压垮数据库。
**解决方案**：
1. **互斥锁 (Mutex Lock)**：缓存失效时，只有一个线程能去数据库查询并重建缓存，其他线程等待或重试。（go-zero 中的 `core/syncx/SingleFlight` 完美解决此问题）。
2. **逻辑过期**：物理上不设置过期时间，在 Value 中存入逻辑过期时间。发现逻辑过期时，异步开启线程去更新缓存，当前请求返回旧数据。

#### 缓存雪崩 (Cache Avalanche)
**定义**：**大量 Key** 在同一时间集中失效，或者 Redis 宕机，导致大量请求打到数据库。
**解决方案**：
1. **过期时间随机化**：在基础过期时间上增加一个随机值（如 1~5 分钟的随机抖动），避免集中失效。
2. **多级缓存**：本地缓存（如 Go 的 `bigcache` 或 `freecache`） + Redis 分布式缓存。
3. **服务降级与限流**：在网关层或服务层进行限流。

### 4. 分布式锁规范 (基于 go-zero)

在 go-zero 框架中，**严禁手动使用 `SET NX EX` 和 Lua 脚本去造轮子**，必须使用 go-zero 官方提供的 `core/stores/redis.RedisLock` 组件。该组件已经内置了原子加锁、唯一标识（随机字符串）防误删、Lua 脚本安全解锁以及锁重入（续期）等特性。

**标准使用范例**：
```go
import "github.com/zeromicro/go-zero/core/stores/redis"

// 1. 创建锁实例 (rdb 为 *redis.Redis 实例)
lock := redis.NewRedisLock(rdb, "lock:order:process:12345")

// 2. 设置过期时间（必须设置，防止死锁。单位为秒）
lock.SetExpire(5) 

// 3. 尝试获取锁
// AcquireCtx 支持传入 context，内部包含 500ms 的容忍重试机制
acquired, err := lock.AcquireCtx(ctx)
if err != nil {
    return err
}
if !acquired {
    return fmt.Errorf("操作太频繁，请稍后再试") // 或返回特定错误码
}

// 4. 确保释放锁
defer lock.ReleaseCtx(ctx)

// 5. 执行业务临界区代码
// ...
```

**关键注意事项**：
1. **必须设置超时时间**：调用 `SetExpire(seconds)`，否则一旦进程崩溃会导致死锁。
2. **无自动看门狗 (Watchdog)**：go-zero 的 `RedisLock` 默认没有后台自动续期线程。如果业务执行时间可能超过锁的 TTL，需要开发者自行评估 TTL 长度，或者在业务中手动再次调用 `lock.Acquire()` 来刷新 TTL（go-zero 的锁支持同一实例重入续期）。
3. **必须校验 acquired 结果**：`err == nil` 仅代表 Redis 请求成功，不代表拿到了锁，必须判断 `acquired == true`。

## AI 交互指导

当 AI 协助生成涉及 Redis 的 Go 代码时，必须：
1. 检查 Key 的命名是否符合规范。
2. 强制要求所有的缓存 Key **必须设置过期时间 (TTL)**，且针对批量生成的 Key 建议加上随机抖动。
3. 在处理高并发查询逻辑时，主动建议使用 `SingleFlight` 来防止缓存击穿。
4. 在编写更新逻辑时，确保遵循“先更新 DB，后删除 Cache”的策略。
5. 当用户需要实现分布式锁时，**必须**使用 go-zero 的 `redis.NewRedisLock`，并强制加上 `SetExpire` 和 `defer lock.ReleaseCtx()` 逻辑。

