Redis之ZSet数据结构底层原理

zset为有序自动去重的集合数据类型,其编码可以是 zipList或者 skipList

1:ziplist

ziplist 编码的有序集合对象使用压缩列表作为底层实现, 每个集合元素使用两个紧挨在一起的压缩列表节点来保存,第一个节点保存元素的成员(member),而第二个元素则保存元素的分值(score)。  

压缩列表内的集合元素按分值从小到大进行排序,分值较小的元素被放置在靠近表头的方向, 而分值较大的元素则被放置在靠近表尾的方向。

如果我们执行以下 ZADD 命令, 那么服务器将创建一个有序集合对象作为 price 键的值:

 

此处的ziplist与Hash类型中的ziplist是同一个编码。

2:skipList

skiplist 编码的有序集合对象使用 zset 结构作为底层实现, 一个zset 结构同时包含一个字典和一个跳跃表:

 

zset 结构中的 zsl 跳跃表按分值从小到大保存了所有集合元素, 每个跳跃表节点都保存了一个集合元素:跳跃表节点的 object 属性保存了元素的成员,而跳跃表节点的 score 属性则保存了元素的分值。

skipList在Redis中的运用场景只有一个,那就是作为有序列表zset的底层实现。跳跃表可以保证增、删、查等操作时的时间复杂度为O(logN),这个性能可以与平衡树相媲美,但实现方式上却更加简单,唯一美中不足的就是跳表占用的空间比较大,其实就是一种空间换时间的思想。

跳跃表的结构如下所示

 

Redis中跳表一个节点最高可以达到64层,一个跳表中最多可以存储2^64个元素。跳表中,每个节点都是一个skiplistNode,

每个跳表的节点也都会维护着一个score值,这个值在跳表中是按照从小到大的顺序排列好的。

跳表的结构定义如下所示:

 

header:指向跳表的头节点,通过这个指针可以直接找到表头,时间复杂度为O(1);

tail:指向跳表的尾节点,通过这个指针可以直接找到表尾,时间复杂度为o(1);

length:记录跳表的长度,即不包括头节点,整个跳表中有多少个元素;

level:记录当前跳表内,所有节点中层数最大的level;

3:编码转换

当有序集合对象可以同时满足以下两个条件时,对象使用 ziplist 编码:

1.有序集合保存的元素数量小于128个;

2.有序集合保存的所有元素成员的长度都小于64字节;

不能满足以上两个条件的有序集合对象将使用 skiplist 编码。

以上两个条件的上限值是可以修改的,具体请看配置文件中关于 zset-max-ziplist-entries 选项和 zset-max-ziplist-value 选项的说明。对于使用 ziplist编码的有序集合对象来说,当使用 ziplist编码所需的两个条件中的任意一个不能被满足时,程序就会执行编码转换操作,将原本储存在压缩列表里面的所有集合元素转移到zset结构里面,并将对象的编码从ziplist 改为skiplist。

4:要点总结

1:ZSet的编码可以是 ziplist 或者 skiplist。

2:ZSet对象 ziplist 或者 skiplist编码,符合条件时可发生编码转换。

3:跳跃表是ZSet的底层实现之一,除此之外它在 Redis 中没有其他应用。

4:跳跃表中的节点按照分值大小进行排序,当分值相同时,节点按照成员对象的大小进行排序。

5:跳跃表的增删改查

1:查

假设现在要查找9这个节点,步骤如下:

①从head开始遍历,指针指向4这个节点,由于4<9,且同层的下一个指针指向NULL,所以下级一层

②跳到4节点所在的层,同理,4<9,且同层下一个指针指向10,再下降一层

③依次最终跳到第一层,第一层是一个双向链表,由于7<9,所以开始向后遍历,查找到9就返回。

 

2:删

删除的过程前期与查找相似,先定位到元素所在的位置,再进行删除,最后更新一下指针、更新一下最高的层数。

3:改

先是判断这个value是否存在,如果存在就是更新的过程,如果不存在就是插入过程。

4:增

从 head 节点开始,先是在 head 开始降层来查找到最后一个比自己小的节点。

直接上图

 

 

 

 

  • 1
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

不要迷恋发哥

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值