Redis双端链表
双端链表
链表作为数组之外的一种常用序列抽象,是大多数高级语言的基本数据类型,因为 C 语言本身不支持链表类型,大部分 C 程序都会自己实现一种链表类型,Redis 也不例外 —— 实现了一个双端链表结构。
双端链表作为一种常见的数据结构,在大部分的数据结构或者算法书里都有讲解,因此,这一章关注的是 Redis 双端链表的具体实现,以及该实现的 API ,而对于双端链表本身,以及双端链表所对应的算法,则不做任何解释。
读者如果有需要的话,可以参考维基百科的双端链表 词条,里面提供了关于双端链表的一些基本信息。
另外,一些书籍,比如《算法:C 语言实现》 和《数据结构与算法分析》 则提供了关于双端链表的更详细的信息。
双端链表的应用
双端链表作为一种通用的数据结构,在 Redis 内部使用得非常多:既是 Redis 列表结构的底层实现之一,同时为大量 Redis 模块所用,用于构建 Redis 的其他功能。
实现 Redis 的列表类型
双端链表还是 Redis 列表类型的底层实现之一,当对列表类型的键进行操作 ——比如执行 RPUSH 、 LPOP 或 LLEN 等命令时,程序在底层操作的可能就是双端链表。
redis> RPUSH brands Apple Microsoft Google
(integer) 3
redis> LPOP brands
"Apple"
redis> LLEN brands
(integer) 2
redis> LRANGE brands 0 -1
1) "Microsoft"
2) "Google"
Note
Redis 列表使用两种数据结构作为底层实现:
- 双端链表
- 压缩列表
因为双端链表占用的内存比压缩列表要多,所以当创建新的列表键时,列表会优先考虑使用压缩列表作为底层实现,并且在有需要的时候,才从压缩列表实现转换到双端链表实现。
后续章节会对压缩链表和 Redis 类型做更进一步的介绍。
Redis 自身功能的构建
除了实现列表类型以外,双端链表还被很多 Redis 内部模块所应用:
- 事务模块使用双端链表依序保存输入的命令;
- 服务器模块使用双端链表来保存多个客户端;
- 订阅/发送模块使用双端链表来保存订阅模式的多个客户端;
- 事件模块使用双端链表来保存时间事件(time event);
类似的应用还有很多,在后续的章节中我们将看到,双端链表在 Redis 中发挥着重要的作用。
双端链表的实现
双端链表的实现由 listNode
和 list
两个数据结构构成,下图展示了由这两个结构组成的一个双端链表实例: