Redis:有序集合类型zset实现原理

Posted 这瓜保熟么

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Redis:有序集合类型zset实现原理相关的知识,希望对你有一定的参考价值。

和上面的集合对象相比,有序集合对象是有序的。与列表使用索引下标作为排序依据不同,有序集合为每个元素设置一个分数(score)作为排序依据。

①、编码
有序集合的编码可以是 ziplist 或者 skiplist。

ziplist 编码的有序集合对象使用压缩列表作为底层实现,每个集合元素使用两个紧挨在一起的压缩列表节点来保存,第一个节点保存元素的成员,第二个节点保存元素的分值。并且压缩列表内的集合元素按分值从小到大的顺序进行排列,小的放置在靠近表头的位置,大的放置在靠近表尾的位置。

//操作
ZADD price 8.5 apple 5.0 banana 6.0 cherry

//存储顺序


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

typedef struct zset
     //跳跃表
     zskiplist *zsl;
     //字典
     dict *dice;
 zset;

字典的键保存元素的值,字典的值则保存元素的分值;跳跃表节点的 object 属性保存元素的成员,跳跃表节点的 score 属性保存元素的分值。

这两种数据结构会通过指针来共享相同元素的成员和分值,所以不会产生重复成员和分值,造成内存的浪费。

说明:其实有序集合单独使用字典或跳跃表其中一种数据结构都可以实现,但是这里使用两种数据结构组合起来,原因是假如我们单独使用 字典,虽然能以 O(1) 的时间复杂度查找成员的分值,但是因为字典是以无序的方式来保存集合元素,所以每次进行范围操作的时候都要进行排序;假如我们单独使用跳跃表来实现,虽然能执行范围操作,但是查找操作有 O(1)的复杂度变为了O(logN)。因此Redis使用了两种数据结构来共同实现有序集合。

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

1、保存的元素数量小于128;

2、保存的所有元素长度都小于64字节。

不能满足上面两个条件的使用 skiplist 编码。以上两个条件也可以通过Redis配置文件zset-max-ziplist-entries 选项和 zset-max-ziplist-value 进行修改。

以上是关于Redis:有序集合类型zset实现原理的主要内容,如果未能解决你的问题,请参考以下文章

学习笔记Redis中有序集合zset的实现原理——跳表

redis中zset原理

Redis数据类型—ZSet

Redis数据类型—ZSet

Redis数据类型—ZSet

[Redis6]常用数据类型_Zset有序集合