2. Redis 缓存基础回顾:核心数据结构、过期策略、内存淘汰机制
在深入异步导出任务的降级与补偿设计之前,必须夯实 Redis 缓存的基础知识。本章将系统回顾 Redis 的五大核心数据结构、键的过期策略以及内存淘汰机制,为后续章节中缓存失效、数据一致性、资源隔离等设计决策提供理论支撑。
2.1 五大核心数据结构
Redis 之所以能成为缓存领域的首选,很大程度上归功于其丰富且高效的数据结构。每种结构都对应特定的应用场景,理解它们的底层实现与适用边界,是设计缓存方案的第一步。
| 数据结构 | 底层编码 | 典型命令 | 核心应用场景 |
|---|---|---|---|
| String | int / embstr / raw | SET / GET / INCR / DECR | 计数器、分布式锁、Session 共享、对象 JSON 缓存 |
| Hash | ziplist / hashtable | HSET / HGET / HGETALL / HINCRBY | 对象字段缓存(如用户信息)、短结构化数据 |
| List | quicklist | LPUSH / RPUSH / LPOP / BRPOP | 消息队列、时间线、最新消息列表 |
| Set | intset / hashtable | SADD / SMEMBERS / SINTER / SUNION | 标签系统、好友关系、去重统计 |
| Sorted Set | ziplist / skiplist + hashtable | ZADD / ZRANGE / ZREVRANGE / ZSCORE | 排行榜、延时队列、优先级任务调度 |
设计提示: 在异步导出任务中,Sorted Set 常用于构建延时队列(以时间戳作为 score),String 用于存储任务状态与进度,Hash 则适合缓存导出任务的元数据(如文件名、行数、创建时间)。选择合适的数据结构能显著降低代码复杂度。
下图展示了五种核心数据结构在内存中的逻辑形态与典型操作路径:
2.2 过期策略:TTL 与惰性删除
Redis 允许为每个键设置生存时间(TTL),到期后自动删除。这一机制是缓存失效的核心驱动力。Redis 采用 定期删除 + 惰性删除 的组合策略来平衡 CPU 与内存开销。
- 定期删除(Active Expiry): Redis 每隔 100ms 随机抽取一部分设置了过期时间的 key,检查是否过期,若过期则删除。该策略避免了全量扫描带来的性能抖动。
- 惰性删除(Lazy Expiry): 当客户端访问一个 key 时,Redis 会先检查该 key 是否已过期,若过期则立即删除并返回 nil。该策略确保了过期 key 不会被返回给客户端。
关键结论: 定期删除负责“主动清理”,惰性删除负责“兜底清理”。两者配合,既保证了过期 key 不会长期占用内存,又避免了定时扫描对 CPU 的冲击。在异步导出任务中,合理设置 TTL 可以自动清理过期任务记录,减少人工干预。
下图展示了过期策略的执行流程与交互关系:
2.3 内存淘汰机制:当内存不足时
当 Redis 内存使用量达到 maxmemory 限制时,会触发内存淘汰策略。这一机制决定了哪些 key 会被优先删除以释放空间。理解不同淘汰策略的行为,对于设计缓存失效后的降级逻辑至关重要。
| 淘汰策略 | 淘汰范围 | 淘汰依据 | 适用场景 |
|---|---|---|---|
| noeviction | 不淘汰 | 直接返回 OOM 错误 | 不允许丢失任何数据的场景(如支付状态) |
| allkeys-lru | 所有 key | 最近最少使用 | 通用缓存,优先保留热点数据 |
| volatile-lru | 设置了 TTL 的 key | 最近最少使用 | 仅淘汰可过期数据,保护持久化 key |
| allkeys-random | 所有 key | 随机 | 数据访问频率均匀,无热点 |
| volatile-random | 设置了 TTL 的 key | 随机 | 对淘汰顺序无要求,仅淘汰可过期数据 |
| volatile-ttl | 设置了 TTL 的 key | 剩余 TTL 最短 | 优先淘汰即将过期的数据 |
| volatile-lfu (4.0+) | 设置了 TTL 的 key | 最不经常使用 | 淘汰访问频率最低的可过期数据 |
| allkeys-lfu (4.0+) | 所有 key | 最不经常使用 | 淘汰全局访问频率最低的数据 |
避坑指南: 在异步导出任务中,如果使用 noeviction 策略,当内存写满时所有写入操作都会失败,可能导致任务状态无法更新、队列无法入队。建议使用 allkeys-lru 或 volatile-lru,并配合监控告警,确保缓存失效时任务系统能优雅降级。
2.4 过期与淘汰的协同关系
过期策略与内存淘汰机制并非独立运行,它们共同决定了 Redis 中数据的生命周期。理解两者的协同关系,有助于设计更健壮的缓存失效补偿方案。
- 优先级: 过期删除的优先级高于内存淘汰。Redis 会先尝试通过定期删除和惰性删除释放空间,若仍不足,再触发内存淘汰。
- 触发条件: 过期删除由 TTL 驱动,内存淘汰由
maxmemory阈值驱动。两者可能同时发生,但互不干扰。 - 数据流向: 一个 key 可能先被过期删除,也可能先被内存淘汰。对于设置了 TTL 的 key,过期删除是“主动退休”,内存淘汰是“被动清退”。
- 设计建议: 在异步导出任务中,建议为所有缓存 key 设置合理的 TTL,并选择 volatile-lru 策略。这样既能保证热点数据优先保留,又能确保非热点数据在内存不足时被淘汰,同时持久化 key(如任务配置)不受影响。