redis为什么要使用skiplist跳表

Posted bitcarmanlee

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了redis为什么要使用skiplist跳表相关的知识,希望对你有一定的参考价值。

1.什么是skiplist跳表

跳表是一种特殊的链表,特殊的点在于其可以进行二分查找。普通的链表要查找元素只能挨个遍历链表中的所有元素,而跳表则利用了空间换时间的策略,在原来有序链表的基础上面增加了多级索引,然后利用类似二分查找的思路来快速实现查找功能。跳表可以支持快速的查找,插入,删除等操作,时间复杂度为O(logn),空间复杂度为O(n)。

2.随机层数的计算

跳表在节点插入时候,会随机出一个层数,依靠这个随机数操作构建的多层链表结构,能保证一个比较好的查找性能。这个随机层数不是一个普通的服从均匀分布的随机数,具体的计算逻辑如下

1.首先,每个节点肯定都有第1层指针(每个节点都在第1层链表里)。
2.如果一个节点有第i层(i>=1)指针(即节点已经在第1层到第i层链表中),那么它有第(i+1)层指针的概率为p。
3.节点最大的层数不允许超过一个最大值,记为MaxLevel。

伪代码如下

randomLevel()
    level := 1
    // random()返回一个[0...1)的随机数
    while random() < p and level < MaxLevel do
        level := level + 1
    return level

randomLevel逻辑中包含有两个参数,一个是概率p,一个是最大层数MaxLevel。在redis的实现中,这两个参数分别为

p = 1/4
MaxLevel = 32

该部分内容来自于如下文档:

skiplist的算法性能分析

关于跳表本身更详细的讲解可以参考上述文档。

3.redis为什么要使用跳表

经常会有人问这个问题,redis中为什么要使用跳表?

这个问题,redis作者已经给出过明确答案

  1. They are not very memory intensive. It’s up to you basically. Changing parameters about the probability of a node to have a given number of levels will make then less memory intensive than btrees.

  2. A sorted set is often target of many ZRANGE or ZREVRANGE operations, that is, traversing the skip list as a linked list. With this operation the cache locality of skip lists is at least as good as with other kind of balanced trees.

  3. They are simpler to implement, debug, and so forth. For instance thanks to the skip list simplicity I received a patch (already in Redis master) with augmented skip lists implementing ZRANK in O(log(N)). It required little changes to the code.

按照我自己的理解,稍微翻译一下就是
1.跳表不是非常吃内存,并且基本是取决于你自己。你可以通过改变参数p(第二部分中提到的),从而达到比btree消耗更少内存的目的。

2.redis中的zset结构经常会使用ZRANGE或者ZREVRANGE这种操作,这个时候遍历跳表就相当于遍历一个普通的链表。这种情况下,跳表的表现跟btree一样优秀。

3.很多人认为这一点是最重要的原因。跳表实现起来更容易,只需要一点点代码就能达到效果,修改起来也很方便。

以上是关于redis为什么要使用skiplist跳表的主要内容,如果未能解决你的问题,请参考以下文章

SkipList跳表基本原理

SkipList跳表基本原理

跳表 SkipList

五Redis源码数据结构之跳表skiplist

skiplist(跳表)的原理及JAVA实现

跳跃表 SkipList数据结构原理及实现