有序集合
有序集合的编码可以是 ziplist 或者 skiplist 。
ziplist编码
ziplist 编码的有序集合对象使用压缩列表作为底层实现, 每个集合元素使用两个紧挨在一起的压缩列表节点来保存, 第一个节点保存元素的成员(member), 而第二个元素则保存元素的分值(score)。
压缩列表内的集合元素按分值从小到大进行排序, 分值较小的元素被放置在靠近表头的方向, 而分值较大的元素则被放置在靠近表尾的方向。
skiplist编码
skiplist 编码的有序集合对象使用 zset 结构作为底层实现, 一个 zset 结构同时包含一个字典和一个跳跃表:
typedef struct zset {
zskiplist *zsl;
dict *dict;
} zset;
zsl 跳跃表按分值从小到大保存了所有集合元素, 每个跳跃表节点都保存了一个集合元素: 跳跃表节点的 object 属性保存了元素的成员,score 属性则保存了元素的分值。
通过这个跳表,可以保证对象有序,而且可以使用范围型的操作。
dict 字典为有序集合创建了一个从成员到分值的映射, 字典中的每个键值对都保存了一个集合元素: 字典的键保存了元素的成员, 而字典的值则保存了元素的分值。
通过这个字典,就可以以O(1)的时间复杂度查询到元素。
这种底层哈希表加链表的结构十分像java中的LinkedHashMap。
编码的转换
当有序集合对象可以同时满足以下两个条件时, 对象使用 ziplist 编码:
- 有序集合保存的元素数量小于
128个; - 有序集合保存的所有元素成员的长度都小于
64字节;