【Redis】双向链表结构
目录
- 1、背景
- 2、双向链表
- 【1】底层结构
- 【2】特性
- 【3】优缺点
1、背景
redis的list类型在旧版本数据量小的时候用的压缩列表,数据量大的时候用双向链表,新版本使用快速列表,接下来就来讲一下redis(6.2.18版本)双向链表的底层结构。
2、双向链表
【1】底层结构
双向链表的每一个节点底层结构如下:
typedef struct listNode {struct listNode *prev; //指向上一个链表节点struct listNode *next; //指向下一个链表节点void *value; //节点的值
} listNode;
多个节点组成一个链表的底层结构如下:
typedef struct list {listNode *head; //链表头节点listNode *tail; //链表尾节点void *(*dup)(void *ptr); //节点值复制函数void (*free)(void *ptr); //节点值释放函数int (*match)(void *ptr, void *key); //节点值比较函数unsigned long len; //链表节点数量
} list;
【2】特性
双向链表的特性如下:
特性 | 实现方式 |
---|---|
双向遍历 | 每个listNode包含prev和next指针,支持前后向遍历 |
无环链表 | 头节点的prev和尾结点的next均为NULL |
长度缓存 | list.len直接记录节点数,无需遍历(O(1)时间复杂度) |
多态支持 | 通过dup、free、match函数指针,支持任意类型的值(如字符串、整数等) |
【3】优缺点
双向链表的优缺点如下:
特性 | 优点 | 缺点 |
---|---|---|
时间复杂度 | 头部/尾部插入、删除:O(1)长度获取 | 随机访问:O(n)需遍历节点 |
内存占用 | 支持动态扩容,无需连续内存 | 每个节点需存储prev和next指针 |
功能灵活性 | 支持双向遍历,可存储任意类型数据 | 无内置压缩机制,存储小数据时内存利用率低 |
实现复杂度 | 结构简单,易于维护和扩展 | 大量小节点内存碎片化风险 |
适用场景 | 频繁头部/尾部操作(如LPUSH、RPOP) | 存储大量小数据时不如ziplist节省内存 |