在写redis系列的第一篇《【Redis 一】Jedis操作Redis有序集合类型(SortedSet)》中就已经单独的用着最高级的操作来开篇了,然后再用一篇来解读 何为高级。
一、sortedset的高级
第一点,是sortedset 如其名,既是拥有了set集合对象的特性,还是有序的,怎么实现的有序呢?它增加了一个分值(权重)score来设置单独的value,使得集合中的元素能够按score进行有序排列。
比set集合对象多了那么一点点就是高级了,社会资源会在头部,而头部只有20%,唯有每次优秀一点点,长期以往才可能在头部的位置。
第二点,sortedset的两种编码分别是ziplist和skiplist。
//跳跃表和字典
#define OBJ_ENCODING_SKIPLIST 7 /* Encoded as skiplist */
//压缩列表
#define OBJ_ENCODING_ZIPLIST 5 /* Encoded as ziplist */
#ziplist 和skiplist 的编码输出
压缩列表 REDIS_ENCODING_ZIPLIST "ziplist"
跳跃表和字典 REDIS_ENCODING_SKIPLIST "skiplist"
/*有序集合对象和其编码类型*/
#使用压缩列表实现的有序集合对象。
REDIS_ZSET REDIS_ENCODING_ZIPLIST
使用跳跃表和字典实现的有序集合对象。
REDIS_ZSET REDIS_ENCODING_SKIPLIST
什么时候使用ziplist呢?满足以下两个条件?:
- 元素个数小于128个(刚好是四分之一的列表对象的限制[512])
- 其中每一个number的长度小于64字节
在redis配置文件redis.conf中可以通过设置zset-max-ziplist-entries和zset-max-ziplist-value来修改
使用ziplist编码的有序集合对象sortset通过ziplist是由两个紧挨在一起链表节点(listnode)表示的,我们从 添加一个有序元素 zadd key score member 命令上就可以发现 key,score,member是同时设置的,score和member是同时作为value被存在list里面,member放在第一个节点,score放在第二个节点。ziplist内的集合元素按score从小到大排序,score较小的排在表头位置。
当超出设定的元素个数或者member的长度时则使用了skiplist编码的方式来实现。使用skiplist编码的有序集合底层是一个命名为zset
的结构体,而一个zset结构同时包含一个字典和一个跳跃表。如下图所表示?:
#有序集合
typedef struct zset {
// 字典,键为成员,值为分值,用于支持 O(1) 复杂度的按成员取分值操作
dict *dict;
// 跳跃表,按分值排序成员,用于支持平均复杂度为 O(log N) 的按分值定位成员操作
// 以及范围操作
zskiplist *zsl;
} zset;
skiplist 跳跃表 是有序的数据结构,通过每个节点维持多个指向其他节点的指针来实现快速访问节点。skiplist 跳跃表 有两种结构 redis.h/zskiplistNode
和 redis.h/zskiplist。