👉 压缩列表省内存但操作慢,双向链表耗内存但操作快
🧠 一、结构本质不同
1️⃣ 压缩列表(ziplist)
👉 一块连续内存
| entry1 | entry2 | entry3 | entry4 |
特点:
- 所有数据挤在一起(类似数组)
- 每个元素记录:
- 前一个元素长度(prevlen)
- 当前数据长度
- 数据内容
2️⃣ 双向链表(linkedlist)
👉 每个节点独立内存 + 指针连接
node1 <-> node2 <-> node3 <-> node4
每个节点:
- prev 指针
- next 指针
- value
⚖️ 二、核心差异对比
| 维度 | 压缩列表(ziplist) | 双向链表 |
|---|---|---|
| 内存占用 | ✅ 很低 | ❌ 很高 |
| 内存结构 | 连续 | 分散 |
| 查找 | ❌ O(n) | ❌ O(n) |
| 插入/删除 | ❌ 慢(需要搬移内存) | ✅ 快(改指针) |
| 缓存命中率 | ✅ 高(连续内存) | ❌ 低 |
| 扩容 | ❌ 可能整体重分配 | ✅ 不需要 |
| 数据量适合 | 小数据 | 大数据 |
🚨 三、最关键的痛点(面试必问)
👉 压缩列表的“连锁更新”问题
当你插入一个元素时:
entry1 | entry2 | entry3
如果 entry2 长度变化:
👉 entry3 的 prevlen 可能变大
👉 entry4 也要变
👉 可能引发连锁修改(cascade update)
结果:
- 插入一次 → 多次内存拷贝
- 最坏 O(n²)
🚀 四、Redis 实际使用策略
Redis 并不是二选一,而是:
👉 小数据用压缩列表,大数据自动切换结构
例如:
List
- 小:ziplist
- 大:linkedlist(新版本是 quicklist)
Hash / ZSet
- 小:ziplist
- 大:hashtable / skiplist
🔥 五、现代 Redis(重要升级)
从 Redis 3.2+ 开始:
👉 ziplist + linkedlist 被优化为:quicklist
quicklist = 压缩列表 + 链表
结构:
node -> ziplist
node -> ziplist
node -> ziplist
优点:
- 保留 ziplist 的内存优势
- 避免大规模内存搬移
- 插入删除更快
🧩 六、你可以这样理解(很形象)
| 类型 | 类比 |
|---|---|
| 压缩列表 | 一整本笔记本(写满页) |
| 双向链表 | 一张张便利贴 |
| quicklist | 一本笔记本 + 分章节 |
✅ 七、总结一句话
👉 压缩列表:空间换时间(省内存)
👉 链表:时间换空间(操作快)
