Redis学习笔记-QuickList
文章目录
- 第一部分:Quicklist 是什么?
- 第二部分:什么数据结构的底层用到了 Quicklist?
- 可配置的内部 `ziplist` 大小
- 总结
第一部分:Quicklist 是什么?
Quicklist
(快速列表)是 Redis 从 3.2 版本开始引入的一种混合数据结构。为了理解它,我们可以用一句话来概括:
Quicklist 本质上是一个由 ziplist
(压缩列表) 节点组成的双向链表。
它被设计出来,旨在结合 ziplist
和 linkedlist
(双向链表)各自的优点,同时规避它们的缺点,从而在内存效率和操作性能之间找到一个完美的平衡点。
用一个形象的比喻来理解:
- 旧的
linkedlist
就像一列卧铺火车,每节车厢(节点)只睡一个乘客(元素),乘客上下车很快,但车厢本身(指针)很占空间,非常浪费。 - 旧的
ziplist
就像一辆超长的公交车,所有乘客都挤在一块连续的空间里,非常省地方。但如果中间有个人要下车,他后面所有人都得往前挪,效率极低(连锁更新问题)。 - 新的
quicklist
就像一列现代的动车组:- 整列动车是一个双向链表。
- 每一节车厢 (
quicklistNode
) 就是链表的一个节点。 - 车厢内部有很多座位,这些座位就是一个
ziplist
,里面坐着多个乘客(元素)。
通过这种方式,quicklist
实现了:
- 高内存效率:每个节点 (
quicklistNode
) 内部用ziplist
存储多个元素,极大地减少了prev
和next
指针的内存开销。 - 高性能:在列表的两端进行
PUSH
和POP
操作时,只需要操作头尾节点 (quicklistNode
) 内部的ziplist
,时间复杂度依然是 O(1)。 - 规避风险:即使发生“连锁更新”,也只会影响单个
ziplist
(一节车厢),而不会影响整个列表(整列火车),将风险控制在了一个很小的范围内。
第二部分:什么数据结构的底层用到了 Quicklist?
在当前的 Redis 版本中,列表 (List) 数据类型是唯一使用 quicklist
作为其底层实现的结构。
quicklist
是专门为了优化 List
类型而设计的。在 Redis 3.2 之前,List
类型的底层实现是根据元素数量和大小在 ziplist
和 linkedlist
之间切换的:
- 当列表小的时候,使用
ziplist
以节省内存。 - 当列表变大后,自动转换为
linkedlist
以保证操作性能。
这种转换机制本身有开销,并且两种结构各自的缺点都很明显。因此,quicklist
被创造出来,彻底取代了 ziplist
+ linkedlist
的组合,成为 List
类型唯一的、更优的底层实现。
你可以通过 OBJECT ENCODING
命令来验证这一点:
redis> RPUSH mylist "a" "b" "c" "d"
(integer) 4
redis> OBJECT ENCODING mylist
"quicklist"# 即使只有一个元素,也是 quicklist
redis> RPUSH smalllist "hello"
(integer) 1
redis> OBJECT ENCODING smalllist
"quicklist"
可配置的内部 ziplist
大小
quicklist
的一个强大之处在于,每个节点内部的 ziplist
的大小是可以通过配置项 list-max-ziplist-size
来调整的。这个参数可以接受正值或负值:
- 负值(默认):按字节大小限制。例如
-2
(默认值) 表示每个ziplist
的大小不能超过 8KB。 - 正值:按元素个数限制。例如
1024
表示每个ziplist
最多包含 1024 个元素。
这个配置项允许用户根据自己的业务场景,在“更多 ziplist
节点、更少连锁更新风险”和“更少 ziplist
节点、更高内存压缩率”之间进行权衡。
总结
问题 | 答案 |
---|---|
Quicklist 是什么? | 一个由 ziplist 节点组成的双向链表,是一种混合数据结构。 |
什么数据结构用到了它? | 列表 (List) 类型。它是当前版本 List 唯一的底层实现。 |
List的实现有3种:LinkedList,QuickList和ZipList