Redis跳跃表查找技巧分享,探索其高效优点与实现原理

文章导读
跳跃表是一种有序的数据结构,它可以在链表的基础上,通过添加额外的“索引层”来快速查找目标元素。这个想法在20世纪90年代由威廉·普在论文中提出(参考来源:William Pugh的论文《Skip Lists: A Probabilistic Alternative to Balanced Trees》)。简单来说,你想象一个排好队的队伍,通常要从头到尾找人,需要一个个问过去。但如果给队伍里的一些人
📋 目录
  1. A 了解跳跃表的基本概念
  2. B 跳跃表为什么查找那么快
  3. C Redis中跳跃表的具体实现方式
  4. D 跳跃表带来的实际好处
A A

了解跳跃表的基本概念

跳跃表是一种有序的数据结构,它可以在链表的基础上,通过添加额外的“索引层”来快速查找目标元素。这个想法在20世纪90年代由威廉·普在论文中提出(参考来源:William Pugh的论文《Skip Lists: A Probabilistic Alternative to Balanced Trees》)。简单来说,你想象一个排好队的队伍,通常要从头到尾找人,需要一个个问过去。但如果给队伍里的一些人贴上“小组长”的标签,并且这些“小组长”也知道其他“小组长”的位置,那么找人时就可以先问“小组长”,快速跳过一大段人,然后再慢慢缩小范围。Redis就是用这种聪明的方式,在它的有序集合等地方实现了跳跃表,让它比单纯的链表快得多。(参考来源:Redis官方文档关于有序集合的实现)

跳跃表为什么查找那么快

这主要是因为跳跃表使用了“多层索引”的技巧。在普通的链表里,查找一个元素需要从头到尾遍历,如果链表很长,就会很慢。而跳跃表会随机地为一些元素创建多个层级的“高架桥”。比如第一层是所有元素都有的基础链表,第二层随机选一半元素作为索引,第三层再随机选一半,以此类推。查找时,从最高层开始,像滑雪一样快速滑过大量元素,然后逐步下降到低层,精确找到目标。根据William Pugh的分析,这种结构平均查找时间复杂度是O(log n),和平衡树类似,但实现起来更简单,不需要复杂的旋转操作来保持平衡。同时,Redis还根据实际数据特点做了优化,比如设置最大层数限制,避免索引过大。(参考来源:Redis源码中关于跳跃表的实现注释)

Redis中跳跃表的具体实现方式

在Redis里,跳跃表被用在有序集合(zset)等数据结构中。具体来说,它用一个结构体来代表跳跃表节点,每个节点有这些部分:一是“分值”,用来排序;二是“成员对象”,比如一个字符串;三是一个“层”数组,每层记录了指向下一个节点的指针和“跨度”(就是两个节点之间的间隔)。创建新节点时,Redis会随机决定这个节点有多少层,层数越高,它在索引中的作用越大。插入元素时,先从高层开始找到合适位置,然后像“插队”一样调整指针。删除和更新也类似,但Redis会小心处理,确保索引不会乱掉。整个过程避免了使用复杂的平衡算法,所以代码更简洁,且在实际中效率很高。(参考来源:Redis源码中的zset.c文件)

跳跃表带来的实际好处

相比于其他数据结构比如平衡树,跳跃表有几个显著优点。一是它更容易实现和维护,不需要像红黑树那样复杂的规则来保持平衡,这在软件工程中是很大的优势,因为简单意味着更少出错。二是它在高并发环境下表现更好,虽然Redis是单线程的,但跳跃表的简单性也让其易于扩展。三是跳跃表支持快速的区间查询,比如在有序集合中查找分数在某个范围内的所有成员,这得益于它的有序性和多层索引。根据Redis的测试,在实际应用中,跳跃表提供了稳定的高性能,尤其是在数据量大的时候,查找、插入和删除操作都能保持快速。当然,它也有一些小缺点,比如需要额外的内存来存储索引,但Redis通过合理的设计,如限高层数,控制了这个开销。(参考来源:Redis官方文档关于性能的说明)