当一个列表键(key-value 中的 value 为 list)包含了数量较多的元素,又或者列表中包含的元素都是比较长的字符串时,Redis 就会使用 链表作为列表键的底层实现
1. 链表的用处
- 某些情况下用作列表键
- 客户端输出缓冲区
2. 链表和链表节点的实现
每个链表节点使用了一个 adlist.h/listNode 结构来表示
typedef struct listNode{
//前置节点
struct listNode *prev;
//后置节点
struct listNode *next;
//节点的值
void *value;
}
多个 listNode 可以组成一个双向链表

链表使用一个 adlist.h/list 来实现
typedef struct list{
//表头节点
listNode *head;
//表尾节点
listNode *tail;
//链表所包含的节点数量
unsigned ling len;
//节点值复制函数
void *(*dup) (void *ptr);
//节点值释放函数
void (*free)(void *ptr)
//节点值对比函数
int (*match) (void *ptr, void *key);
}

3. Redis 链表的特性
双端:链表节点带有 prev 和 next 指针,获取猴哥节点的前置节点和后置节点的复杂度都为 O(1)
无环:表头节点的 prev 和表尾节点的 next 指针都指向 NULL, 对链表访问以 NULL 结束
带表头和表尾指针 :通过 list 结构的 head 指针和 tail 指针,程序获取链表表头和表尾的复杂度都为 O(1)
带链表长度计数器:链表中存有记录链表长度的属性 len
多态:链表节点使用 void* 指针来保存节点值,并且可以通过 list 结构的 dup 、 free、 match 三个属性为节点值设置类型特定函数。
参考资料
[1].《Redis 设计与实现》