Redis 基础回顾:数据结构概览、常用命令、键空间与过期策略

在深入缓存契约版本校验之前,必须夯实 Redis 核心基础。本章将系统梳理 Redis 的五大核心数据结构、对应的常用命令、键空间管理机制以及过期策略,为后续的版本号存储、序列化与校验逻辑打下坚实的理论基础。

1. 五大核心数据结构概览

Redis 并非简单的键值存储,其 value 支持多种数据结构。理解每种结构的底层实现与适用场景,是设计高效缓存契约的关键。

数据结构 底层编码(主要) 最大元素数 典型应用场景
String int / embstr / raw 512 MB 缓存版本号、计数器、JSON 序列化对象
Hash ziplist / hashtable 2^32 - 1 个 field 存储对象字段级版本、结构化缓存
List quicklist 2^32 - 1 个元素 消息队列、版本变更日志
Set intset / hashtable 2^32 - 1 个元素 标签去重、版本白名单
Sorted Set ziplist / skiplist 2^32 - 1 个元素 版本号排序、时间窗口校验
契约提示: 在版本校验场景中,Hash 结构最适合存储带有多个版本字段的缓存对象(如 contract:v1:user:123),而 String 则适合存储单一的全局版本号。

2. 常用命令速查

以下命令是日常操作与版本校验中的高频指令,按数据结构分类整理。

2.1 通用命令(键空间操作)

  • EXISTS key — 检查键是否存在,返回 1 或 0。
  • TYPE key — 返回键存储的数据结构类型。
  • DEL key [key ...] — 删除一个或多个键。
  • EXPIRE key seconds — 设置键的生存时间(秒)。
  • TTL key — 查看键剩余的生存时间(秒)。
  • RENAME key newkey — 重命名键。

2.2 String 命令

  • SET key value [NX|XX] [EX seconds] — 设置值,支持条件与过期。
  • GET key — 获取值。
  • MGET key [key ...] — 批量获取。
  • INCR key — 原子自增 1,常用于版本号递增。
  • GETSET key value — 设置新值并返回旧值。

2.3 Hash 命令

  • HSET key field value — 设置单个字段。
  • HGET key field — 获取单个字段。
  • HMSET key field value [field value ...] — 批量设置。
  • HGETALL key — 获取所有字段与值。
  • HEXISTS key field — 检查字段是否存在。
  • HDEL key field [field ...] — 删除字段。

2.4 其他结构常用命令

结构 命令示例 说明
List LPUSH / RPUSH / LPOP / RPOP / LRANGE 队列操作,支持阻塞版本 BLPOP
Set SADD / SMEMBERS / SISMEMBER / SINTER 集合运算,适合版本交集校验
Sorted Set ZADD / ZRANGE / ZREVRANGE / ZSCORE 按分数排序,版本号可作为 score
# 示例:使用 Hash 存储契约版本信息
HSET contract:user:1001 version 2.1.0 data "{...}" updated_at 1700000000
HGET contract:user:1001 version
# 返回 "2.1.0"

3. 键空间(Keyspace)与过期策略

Redis 的键空间是一个全局字典,所有键都存储在其中。理解键空间的扫描与过期机制,对于避免版本校验中的性能陷阱至关重要。

3.1 键空间扫描

  • KEYS pattern — 阻塞式扫描,返回所有匹配的键。生产环境禁止使用,会阻塞单线程。
  • SCAN cursor [MATCH pattern] [COUNT count] — 游标式增量迭代,无阻塞,适合版本键的批量发现。
性能警告: 在版本校验中,如果需要查找所有以 contract:v2: 开头的键,必须使用 SCAN 而非 KEYS。单次 KEYS 在百万级键空间下可能导致 Redis 服务中断。

3.2 过期策略

Redis 使用三种策略组合来清理过期键:

  1. 被动过期(惰性删除): 当客户端访问一个键时,检查其是否过期,若过期则删除并返回 nil。
  2. 主动过期(定期删除): 每 100ms 随机抽取一部分设置了过期时间的键,检查并删除过期键。
  3. 内存淘汰(eviction): 当内存达到 maxmemory 限制时,根据淘汰策略(如 LRU、LFU、TTL)删除键。

在缓存版本校验中,过期策略直接影响版本数据的生命周期:

  • 使用 EXPIRE 或 SET EX 为缓存版本设置 TTL,确保旧版本自动失效。
  • 避免大量键在同一秒过期(雪崩),可在 TTL 上增加随机偏移量。
  • 内存淘汰策略建议使用 allkeys-lru 或 volatile-lru,防止版本数据占满内存。
# 设置版本缓存,10分钟后过期
SET contract:version:user:1001 "2.1.0" EX 600

# 查看剩余生存时间
TTL contract:version:user:1001
# 返回 598(秒)

4. 数据结构与过期策略关系图

下图展示了 Redis 内部键空间、数据结构编码与过期机制之间的协作关系:

Redis 键空间与过期策略架构 全局键空间 String Hash List Set Sorted Set 过期策略 被动过期(惰性删除) 访问时检查并删除 主动过期(定期删除) 每 100ms 随机抽样 内存淘汰(Eviction) LRU / LFU / TTL 版本校验中,建议为每个缓存键设置 TTL,并配合 SCAN 进行增量扫描,避免阻塞

5. 版本校验中的键空间设计建议

最佳实践:

  • 命名规范: 使用 contract:{version}:{entity_type}:{entity_id} 格式,便于 SCAN 匹配。
  • 过期时间: 版本缓存 TTL 建议设置为业务容忍的最大延迟时间 + 随机偏移(如 600 + random(0, 120) 秒)。
  • 批量操作: 使用 MGET / HMGET 减少网络往返,避免在版本校验循环中逐条 GET。
  • 避免大键: 单个 String 值超过 10 KB 时,考虑拆分为 Hash 字段,降低序列化开销。