02.数据结构
文章目录
问题: Redis 支持哪些核心数据类型?请分别说明 String、List、Hash、Set、ZSet 的底层实现(如 SDS、quicklist、ziplist、跳表等),并各举一个典型应用场景。
👇 点击展开/折叠 面试背诵模板(建议先背这个)
各数据类型底层实现详解
① String(字符串)—— SDS
- 不再使用 C 字符串,而是自定义 SDS(Simple Dynamic String),包含长度字段和预分配空间,获取长度 O(1),杜绝缓冲区溢出
- 典型应用:缓存 HTML 片段、分布式锁、计数器(
INCR命令)
② List(列表)—— quicklist(3.2 版本后)
- 由双向链表和 ziplist 组合而成,每个节点是一个 ziplist,既解决了链表内存碎片问题,又解决了普通 ziplist 更新时大规模搬迁的性能问题
- 典型应用:用户最新消息列表(
LPUSH + LRANGE)、阻塞队列(BRPOP)
③ Hash(哈希)—— ziplist / hashtable
- 字段少且值短时使用 ziplist(连续内存,节省空间),字段多或值大时转为哈希表(O(1) 读写)
- 典型应用:存储用户基本信息(如
hset user:1001 name "tom" age 25)、购物车
④ Set(集合)—— intset / hashtable
- 全是整数且数量少时用 intset(有序整数数组,二分查找),否则用哈希表
- 典型应用:抽奖去重、共同好友(
SINTER交集)、用户标签
⑤ ZSet(有序集合)—— ziplist / skiplist + dict
- 数据少时用 ziplist 节省内存,数据多时用跳跃表 + 字典组合:字典提供 O(1) 按值查分值的功能,跳表提供按分值排序和范围查询 O(log N) 功能
- 典型应用:排行榜(按分数排序)、延迟队列(按时间戳排序)
编码转换触发阈值(面试高频补充)
| 数据类型 | 编码转换条件 | 说明 |
|---|---|---|
| Hash | hash-max-ziplist-entries(默认 512)或 hash-max-ziplist-value(默认 64 字节) |
任一超过阈值则从 ziplist 转 hashtable |
| ZSet | zset-max-ziplist-entries(默认 128)或 zset-max-ziplist-value(默认 64 字节) |
任一超过阈值则从 ziplist 转 skiplist + dict |
| Set | set-max-intset-entries(默认 512) |
元素超过 512 个或包含非整数则转 hashtable |
| List | list-max-ziplist-size 相关配置 |
quicklist 中每个 ziplist 节点大小由配置控制,不涉及整体类型转换 |
时间复杂度速查表(面试加分)
| 数据类型 | 核心操作 | 时间复杂度 | 底层依赖 |
|---|---|---|---|
| String | GET/SET |
O(1) | SDS 直接寻址 |
| List | LPUSH/RPOP |
O(1) | quicklist 头尾操作 |
| Hash | HGET/HSET |
O(1) | hashtable(或 ziplist 的 O(N) 但 N 很小) |
| Set | SADD/SISMEMBER |
O(1) | hashtable |
| ZSet | ZADD/ZRANK |
O(log N) | 跳表查找 |
场景选择建议
- 需要计数器、分布式锁 → String
- 需要按顺序消费、最新列表 → List
- 需要存储对象属性且需单独修改某字段 → Hash
- 需要去重、交并补集运算 → Set
- 需要排序、范围查找、按分数聚合 → ZSet
本博客所有文章除特别声明外,均采用 CC BY-NC-SA 4.0 许可协议。转载请注明来源 LGQ的博客!