1. 引言
跳表(Skip List)是一种高效的动态数据结构,在Redis中用于实现有序集合(ZSET),支持快速的范围查询和插入删除操作。相比传统平衡树(如AVL或红黑树),跳表的实现更简单且性能优异。本篇将深入剖析Redis跳表的源码实现,包括结构定义、插入删除逻辑和随机层高生成。
2. 跳表在Redis中的应用
- 用途:ZSET的核心数据结构,存储元素和分数(score),支持按分数排序。
- 特性:结合链表的简单性和二分查找的高效性,平均时间复杂度为O(log n)。
3. 跳表的结构体定义
跳表的实现位于src/server.h
和src/t_zset.c
中。以下是核心结构:
代码片段(server.h
):
typedef struct zskiplistNode {
sds ele; // 元素(SDS字符串)
double score; // 分数
struct zskiplistNode *backward; // 后退指针
struct zskiplistLevel {
struct zskiplistNode *forward; // 前进指针
unsigned long span; // 跨度(到下个节点的距离)
} level[]; // 层数组(柔性数组)
} zskiplistNode;
typedef struct zskiplist {
struct zskiplistNode *header; // 头节点
struct zskiplistNode *tail; // 尾节点
unsigned long length; // 节点数
int level; // 最大层数
} zskiplist;
硬核解析:
zskiplistNode
:每个节点包含元素、分数和多层前进指针(level[]
)。level[i].forward
:指向该层下一个节点。span
:记录跨越的节点数,用于范围查询。backward
:后退指针,便于双向遍历。zskiplist
:管理整个跳表,header
不存储数据,仅作为起点。
Mermaid结构图: