读<<Redis设计与实现>>与redis(5.0)源码__skiplist
结构差异
结构定义在
server.h文件
方法实现在t_zset.c文件(ziplist是压缩)
-
zskiplistNode
1
2
3
4
5
6
7
8
9typedef struct zskiplistNode {
sds ele; // 原本是 robj *obj,表示保存的成员对象
double score; // 分值
struct zskiplistNode *backward; // 后退指针
struct zskiplistLevel {
struct zskiplistNode *forward; // 前进指针
unsigned long span; // 跨度
} level[];
} zskiplistNode; -
zskiplist
1
2
3
4
5typedef struct zskiplist {
struct zskiplistNode *header, *tail; // 表头和表尾
unsigned long length; // 长度,即节点数()不含表头
int level; // 跳跃表内层数最大的节点的层数
} zskiplist;
一些常量
- ZSKIPLIST_P = 0.25,随机level的概率
- ZSKIPLIST_MAXLEVEL = 64,最大level
level的幂次定律
幂次定律: 越大的数出现的概率越小
level为 n的概率大概是 (3/4)^n
1
2
3
4
5
6
7 int zslRandomLevel(void) {
int level = 1;
// 每次1/4的概率往上加
while ((random()&0xFFFF) < (ZSKIPLIST_P * 0xFFFF))
level += 1;
return (level<ZSKIPLIST_MAXLEVEL) ? level : ZSKIPLIST_MAXLEVEL;
}
API
-
zslCreate
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17zskiplist *zslCreate(void) {
int j;
zskiplist *zsl;
zsl = zmalloc(sizeof(*zsl));
zsl->level = 1;
zsl->length = 0;
// 所以头节点是不计算长度的,而且初始化了最大的level但不计算level(算1)
zsl->header = zslCreateNode(ZSKIPLIST_MAXLEVEL,0,NULL);
for (j = 0; j < ZSKIPLIST_MAXLEVEL; j++) {
zsl->header->level[j].forward = NULL;
zsl->header->level[j].span = 0;
}
zsl->header->backward = NULL;
zsl->tail = NULL;
return zsl;
} -
zslInsert
前提保证了元素不存在
看起来有点复杂的
1 |
zskiplistNode *zslInsert(zskiplist *zsl, double score, sds ele) { |
-
zslDelete
-
zslUpdateScore
是先delete,在insert,不复用