整数集合是集合键(set)的底层实现之一,当一个集合只包含整数值元素时,并且这个集合的元素数量不多时,Redis就会用整数集合作为集合键的底层实现。
整数集合的实现
整数集合(intset)是Redis用于保存整数值的集合抽象数据结构,它可以保存类型为int16_t、int32_t或者int64_t的整数值(即16、32、64位的),并且保证集合中不会出现重复元素。
每个intset.h/intset结构表示一个整数集合(是整个set集合)
typedef struct intset{
//编码方式
uint32_t encoding;
//集合包含的元素数量
uint32_t length;
//保存元素的数组
int8_t contents[];
}intset;
-
contents数组是整数集合的底层实现,存储的就是集合里面的元素,而且是按从小到大有序地排列,并且数组中是不包含任何重复项的。
-
length属性记录了整数集合包含的元素数量,即contents数组的长度
注意
contents属性声明为int8_t(8位),但实际上contents数组可能并不保存任何int8_t类型的值,contents数组的真正类型取决于encoding属性的值。
-
如果encoding属性的值为INTSET_ENC_INT16,那么contents就是一个int16_t类型的数组,里面的元素都是一个16位数组( − 2 15 2 15 -2{15}~2{15} −215 215)
-
同理,如果为INTSET_ENC_INT32和INTSET_ENC_INT64,就对应为32位和64位
-
整个数组的字节大小,要通过length属性和encoding属性来计算,比如length值为5,encoding值为int16_t,那么总的字节大小为5*16=80。
下面看一种特殊情况
这是一个encoding属性为INTSET_ENC_INT64的,所以数组是储存64位的元素的数组,但里面除了第一个元素外,其他都不需要这么大的位数,不过根据整数集合的升级规则,当向一个底层位int16_t数组的整数集合中添加一个int64_t类型的整数值时,整数集合已有的所有元素都会被转换成int64_t类型。
升级
当我们要将一个新元素添加到底层数组时,会先比较新元素的位数是否满足,如果新元素的类型比整数集合现有所有的元素都要长时