为什么Redis SortedSet使用Skip List而不是Balanced Tree?

时间:2017-07-15 05:59:25

标签: data-structures redis sortedset skip-lists

Redis文件如下:

  

ZSET是使用两个数据结构来保存相同元素的有序集    为了得到O(log(N))INSERT和REMOVE操作进入排序    数据结构。

     

将元素添加到将Redis对象映射到的哈希表中   分数。同时将元素添加到跳过列表中   将分数映射到Redis对象(因此对象按分数排序)   这个"查看")。

我无法理解。有人可以给我一个详细的解释吗?

2 个答案:

答案 0 :(得分:2)

Antirez说,见https://news.ycombinator.com/item?id=1171423

有几个原因:

  • 他们的内存不是很大。它基本取决于你。更改关于节点具有给定数量级别的概率的参数将使得比btree更少的内存密集。
  • 有序集通常是许多ZRANGE或ZREVRANGE操作的目标,即将跳过列表作为链接列表遍历。通过此操作,跳过列表的缓存位置至少与其他类型的平衡树一样好。
  • 它们更易于实现,调试等等。例如,由于跳过列表的简单性,我收到了一个补丁(已经在Redis master中),其中增加了跳过列表,在O(log(N))中实现了ZRANK。它几乎不需要对代码进行任何更改。

关于仅附加耐久性&速度,我不认为以更多的代码和更复杂的方式优化Redis是一个好主意,因为对于Redis目标(每个命令的fsync(),IMHO应该是罕见的)。即使使用ACID SQL数据库,也几乎没有人使用此功能,因为性能提示无论如何都很大。

关于线程:我们的经验表明Redis主要受I / O限制。我使用线程从虚拟内存中提供服务。利用所有内核的长期解决方案,假设您的链接速度太快以至于可以使单个内核饱和,正在运行多个Redis实例(无锁,几乎完全可以根据内核数量线性扩展),并使用&#34 ; Redis Cluster"我计划在未来发展的解决方案。

答案 1 :(得分:1)

首先,我想我已经了解了Redis文档所说的内容。 Redis有序集按用户指定的元素分数维护元素的顺序。但是当用户使用一些Redis Zset API时,它只提供元素args。例如:

ZREM key member [member ...]
ZINCRBY key increment member
...

redis需要知道这个成员(元素)的值是什么,因此它使用哈希表维护映射,就像文档说的那样:

  

将元素添加到将Redis对象映射到的哈希表中   分数。

当它收到一个成员时,它通过哈希表找到它的值,然后操纵跳过列表上的操作以维持set的顺序。 redis使用两种数据结构来维护双映射,以满足不同API的需要。

我读过William Pugh的论文 Skip Lists:A Probabilistic  替代平衡树,发现跳过列表非常优雅,比旋转更容易实现。

另外,我认为通用二进制平衡树能够同时完成这项工作。我的情况我已经错过了什么,请指出来。