这是我参与8月更文挑战的第8天,活动详情查看:8月更文挑战
一、集合对象
1、集合对象简介
集合对象的编码可以是intset或者hashtable。 intset编码的集合对象使用整数集合作为底层实现,集合对象包含的所有元素都被保存在整数集合里面。
hashtable编码的集合对象使用字典作为底层实现,字典的每个键都是一个字符串对象,每个字符串对象包含了一个集合元素,而字典的值则全部被设置为NULL。
2、集合对象编码转换
当集合对象可以同时满足以下两个条件时,对象使用intset编码:
- 集合对象保存的所有元素都是整数值
- 集合对象保存的元素数量不超过512个。 不能满足这两个条件的集合对象需要使用hashtable编码。
第二个条件的上限值是可以修改的,具体请看配置文件中关于set-max-intset-entries选项说明。
二、有序集合对象
1、有序集合对象简介
有序集合的编码可以是ziplist或者skiplist。 ziplist编码的有序集合对象使用压缩列表作为底层实现,每个集合元素使用两个紧挨在一起的压缩列表节点来保存,第一个节点保存元素的成员(member),而第二个元素则保存元素的分值(score)。
压缩列表内的集合元素按分值从小到大进行排序,分值较小的元素被放置在靠近表头的位置,而分值较大的元素则被放置在靠近表尾的位置。
skiplist编码的有序集合对象使用zset结构作为底层实现,一个zset结构同时包含一个字典和一个跳跃表:
typedef struct zset {
zskiplist *zsl;
dict *dict;
} zset;
1、zset结构中的zsl跳跃表按分值从小到大保存了所有集合元素,每个跳跃表节点都保存了一个集合元素:跳跃表节点的object属性保存了元素的成员,而跳跃表节点的score属性则保存了元素的分值。通过跳跃表,程序可以快速对有序集合进行范围型操作。
2、zset结构中的dict字典为有序集合创建了一个从成员到分值的映射,字典中的每个键值对都保存了一个集合元素:字典的键保存了元素的成员,而字典的值则保存了元素的分值。通过字典特性,程序 可以O(1)复杂度查找给定成员的分值。
有序集合每个元素的成员都是一个字符串对象,而每个元素的分值都是一个double类型的浮点数。虽然zset结构同时使用跳跃表和字典来保存有序集合元素,但两种数据结构都会通过指针来共享相同元素的成员和分值,所以同时使用跳跃表和字典来保存元素欲集合,也不会浪费内存。
为什么有序集合需要同时使用跳跃表和字典来实现呢,你知道吗?
2、有序集合对象编码转换
当有序集合对象可以同时满足以下两个条件时,对象使用ziplist编码:
- 有序集合保存的元素数量小于128个;
- 有序集合保存的所有元素成员的长度都小于64字节; 不能满足以上两个条件的有序集合对象将使用skiplist编码。
以上两个条件的上限值是可以修改的,具体请看配置文件中关于zset-max-intset-entries选项和zset-max-ziplist-value选项的说明。