3. Redis 缓存基础回顾:数据结构、过期策略、内存淘汰机制
在深入多租户 SaaS 鉴权拦截链路之前,必须夯实 Redis 缓存的核心基础。本章将系统回顾 Redis 的五大常用数据结构、键的过期策略以及内存淘汰机制,为后续的令牌验证优化提供理论支撑。
3.1 五大核心数据结构与适用场景
Redis 并非简单的键值存储,其丰富的数据结构决定了不同的缓存效率。下表对比了五种最常用的数据类型及其在鉴权场景中的典型应用:
| 数据结构 | 底层编码 | 核心操作命令 | 鉴权场景示例 |
|---|---|---|---|
| String | int / embstr / raw | SET / GET / INCR / EXPIRE | 单租户令牌(Token)缓存、API 限流计数器 |
| Hash | ziplist / hashtable | HSET / HGET / HGETALL / HDEL | 存储用户会话信息(userId、角色、过期时间) |
| List | quicklist | LPUSH / RPUSH / LPOP / BRPOP | 异步鉴权日志队列、令牌黑名单广播 |
| Set | intset / hashtable | SADD / SISMEMBER / SMEMBERS / SCARD | 租户权限集合、已吊销令牌集合 |
| Sorted Set | ziplist / skiplist | ZADD / ZRANGEBYSCORE / ZREMRANGEBYSCORE | 令牌按过期时间戳排序,实现自动清理 |
架构建议: 在多租户鉴权中,Hash 结构最适合存储租户级配置(如签名密钥、令牌有效期),而 Sorted Set 可用于构建“令牌过期时间索引”,实现高效的批量淘汰。
3.2 过期策略:被动与主动结合
Redis 的过期删除并非实时扫描所有键,而是采用 惰性删除 + 定期删除 的混合策略,以平衡 CPU 与内存开销。
- 惰性删除(Lazy Deletion): 当客户端访问一个键时,Redis 会检查其是否已过期。若过期则立即删除并返回 nil。这种策略对 CPU 友好,但可能导致已过期但未被访问的键长期占用内存。
- 定期删除(Active Deletion): Redis 每隔 100ms 随机抽取一部分设置了过期时间的键进行检查,如果过期则删除。通过调整
hz参数(默认 10)可控制扫描频率。
下图展示了两种策略的协同工作流程:
注意: 如果大量键在同一时间点过期,Redis 的定期删除可能因扫描频率限制而滞后,导致瞬时内存压力。建议在设置令牌过期时间时加入随机偏移量(如 ±10%),避免“雪崩”效应。
3.3 内存淘汰机制:当缓存写满时
当 Redis 使用的内存达到 maxmemory 限制时,会根据配置的淘汰策略(maxmemory-policy)决定如何腾出空间。对于多租户鉴权系统,选择合适的策略至关重要。
Redis 8 种淘汰策略可分为三类:
| 类别 | 策略名称 | 淘汰逻辑 | 鉴权场景适用性 |
|---|---|---|---|
| 不淘汰 | noeviction |
不淘汰任何数据,写入操作直接返回错误 | ❌ 不推荐,会导致鉴权写入失败 |
allkeys-lru |
从所有键中淘汰最近最少使用的键 | ✅ 推荐,自动淘汰低频访问的旧令牌 | |
| 基于 LRU | allkeys-lfu |
从所有键中淘汰最不经常使用的键 | ✅ 适合访问模式稳定的场景 |
volatile-lru |
从设置了过期时间的键中淘汰最近最少使用的 | ⚠️ 需确保所有令牌都设置了过期时间 | |
volatile-lfu |
从设置了过期时间的键中淘汰最不经常使用的 | ⚠️ 同上,需配合过期时间使用 | |
| 基于 TTL | volatile-ttl |
从设置了过期时间的键中淘汰即将过期的 | ✅ 适合令牌缓存,优先淘汰快过期的 |
volatile-random |
从设置了过期时间的键中随机淘汰 | ❌ 不确定性高,可能导致有效令牌被误删 | |
| 随机 | allkeys-random |
从所有键中随机淘汰 | ❌ 不推荐,缺乏业务语义 |
最佳实践: 对于多租户 SaaS 鉴权缓存,推荐使用
allkeys-lru 或 volatile-ttl。前者能自动适应访问模式变化,后者则与令牌的过期语义天然匹配。务必避免使用 noeviction,否则高并发下鉴权服务可能因写入失败而雪崩。
3.4 数据结构与淘汰策略的协同设计
在实际的鉴权拦截链路中,数据结构的选型与淘汰策略需要协同考虑。下图展示了如何利用 Sorted Set 结合 volatile-ttl 策略实现精准的令牌生命周期管理:
通过上述设计,Redis 的内存淘汰机制不再是“盲目”的,而是与业务语义(令牌过期时间)深度绑定,从而在缓存压力下优先保留最“新鲜”的令牌,提升鉴权命中率。