Redis跳表
Redis中的跳表实现在3.0版本是在Redis.h中,到3.2版本时定义到了server.h中。
1 | /* ZSETs use a specialized version of Skiplists */ |
幂次定律
在Redis中,跳表返回的随机层数值使用的算法就是幂次定律。
- 含义是:如果某件事的发生频率和它的某个属性成幂关系,那么这个频率就可以称之为符合幂次定律。
- 表现是:少数几个事件的发生频率占了整个发生频率的大部分,而其余的大多数事件只占整个发生频率的一个小部分。
1
2
3
4
5
6int zslRandomLevel(void) {
int level = 1;
while ((random()&0xFFFF) < (ZSKIPLIST_P * 0xFFFF))//ZSKIPLIST_P(0.25)所以level+1的概率为0.25
level += 1;
return (level<ZSKIPLIST_MAXLEVEL) ? level : ZSKIPLIST_MAXLEVEL;
}
创建跳跃表
1 | /* |
插入节点
1 | /* |
删除节点
1 | /* Internal function used by zslDelete, zslDeleteByScore and zslDeleteByRank |
获取节点排名
1 | /* Find the rank for an element by both score and key. |
区间操作
1 | zskiplistNode *zslFirstInRange(zskiplist *zsl, zrangespec *range) { //返回第一个分数在range范围内的节点 |
为什么Redis要使用跳表来实现有序集合而不是红黑树?
Redis中有序集合支持的核心操作主要有:
- 插入一个数据
- 删除一个数据
- 查找一个数据
- 按照区间查找数据
- 迭代输出有序序列
其中插入、删除、查找以及迭代有序序列这几个操作,红黑树也能够完成,时间复杂度跟跳表是一样的。
但是按照区间查找数据这个操作,红黑树的效率没有跳表高。跳表可以在O(logn)时间复杂度定位区间的起点,然后在原始链表中顺序先后查询,这非常高效。
此外,相比于红黑树,跳表还具有代码更容易实现、可读性高、不容易出错、更加灵活等特点。