1077 字
约 3 分钟
6
S12-B02 · 五种数据结构与底层编码

适用读者:只会用 string 存 JSON 的人。
前置:S12-B01。
实测环境:Redis 7.0.15(2026-11-05)。
覆盖旧文:861(110) 1578(126) 882(91) = 327 点。
覆盖扩展:E-S12-003(编码升级阈值)、E-S12-011(SDS/quicklist 结构)。
上一篇:S12-B01 · 单线程为什么还快
下一篇:S12-B03 · 过期、淘汰与内存。


1. 一句话结论

Redis 的"五种类型"对外是逻辑结构,对内是多种编码:小规模用紧凑编码(listpack/intset),超阈值才升级成标准结构(hashtable/skiplist/quicklist)。

实测:

u   string   embstr
l   list     quicklist
h   hash     listpack
z   zset     listpack
s   set      hashtable
key 类型 编码 为什么
u("hello") string embstr 短字符串一次性分配
l(a,b,c) list quicklist 7.0 的 list 统一 quicklist
h(1 个字段) hash listpack 小 hash 用紧凑数组
z(2 个成员) zset listpack 小 zset 用紧凑数组
s(x,y) set hashtable 字符串成员:7.0 无 listpack set,直接哈希

2. 五种类型与适用场景

类型 结构 典型用途
string 二进制安全字符串 缓存 JSON、计数器(INCR)
hash 字段→值 对象属性、购物车
list 双向链表 队列/栈、简单消息
set 无序集合 去重、交并差(共同好友)
zset 跳表 + 哈希 排行榜、延迟队列(score=时间)

判据:"我要按什么访问数据?" 按 key → string;按字段 → hash;按顺序 → list;去重/集合运算 → set;按分数排序 → zset。


3. 编码升级阈值(E-S12-003)

类型 紧凑编码 升级条件(默认)
string int/embstr 长度 > 44 字节 → raw
hash listpack 字段 > 128 或值 > 64 字节 → hashtable
zset listpack 成员 > 128 或值 > 64 字节 → skiplist
set intset(全整数)/listpack(7.2+) 元素 > 512 或非整数 → hashtable
list quicklist 一直是(内部节点用 listpack)

实测验证:200 个元素的 list 仍然是 quicklist(list 没有"升级"这一说,只有节点内 listpack 的大小)。

"为什么阈值重要":listpack 省内存(无指针),但 O(n) 查找;hashtable 快但占内存。 阈值是"内存 vs 速度"的分界。


4. ZSet 为什么用跳表(A-882)

结构 范围查询 实现复杂度
平衡树 O(log n) 高(旋转)
跳表 O(log n) 低(多层索引 + 随机层高)

跳表的优势:实现简单、支持无锁并发(虽然 Redis 单线程用不上)、范围查询天然有序。

"为什么不用红黑树":范围查询时跳表只需沿底层链表走,红黑树需中序遍历。


5. 内存优化实践

手段 说明
控制元素数 保持在阈值内可省大量内存
用 hash 代替多个 key 小对象聚合(注意别变大 key,A02)
值不要太长 超过 64 字节会升级编码
用 OBJECT ENCODING 检查 上线前确认编码符合预期

6. 五个误区

误区 真相
"五种类型就五种结构" 每类有 2–4 种编码
"list 一定是链表" 是 quicklist(链表 of listpack)
"set 都是哈希表" 全整数时是 intset
"zset 一定用跳表" 小规模用 listpack
"编码不影响性能" 编码决定内存与复杂度

7. 自检

  1. 五种类型各自的典型用途?
  2. embstr 与 raw 的分界是多少字节?
  3. hash 什么时候从 listpack 升级?
  4. zset 为什么选跳表而不是红黑树?
  5. 怎么确认一个 key 的实际编码?

8. 下一篇

S12-B03 · 过期、淘汰与内存

编码讲完,下一篇讲"内存满了怎么办":过期删除策略与八种淘汰策略(含实测淘汰 29,803 个 key)。


本篇属于系列《S12 · Redis 与缓存》。旧文来源:A-861/1578/882;扩展点 E-S12-003/011。编码输出为 Redis 7.0.15 实测。

S12-B02 · 五种数据结构与底层编码
https://www.clxhxhhr.top/posts/5346/
作者
clxstart
发布于
2024-12-31
许可协议
CC BY-NC-SA 4.0
评论
0 条
还没有评论,先写一条吧。