概述
整数集合(intset)是集合键的底层实现之一,当一个集合只包含整数值元素,并且这个集合的元素数量不多时,Redis就会使用整数集合作为集合键的底层实现。它可以保存类型为int16_t、int32_t或者int64_t的整数值,并且保证集合中不会出现重复元素。
实现
整数集合使用intset.h/intset结构表示:
typedef struct intset{
//编码方式
uint32_t encoding;
//集合包含的元素数量
uint32_t length;
//保存元素的数组
int8_t contents[];
}intset;
如图展示的是一个保存16位整数的整数集合,encoding表示整数集合内元素的编码方式,会根据插入的元素自动调整,length保存着集合内元素的数量,contents数组是数据实际保存的位置。
升级
每当我们要将一个新元素添加到整数集合里面,并且新元素不在整数集合编码方式的表示范围内时,整数集合需要先进行升级。例如整数集合当前是16位整型编码,可表示的范围为:-32768~32767,当新加入的元素不在此范围,比如32768需要32位整型才能表示,或者更大的数,需要64位整型,就需要对整数集合进行升级才能保存。升级会重新为contents数组分配空间,并将数组内的所有元素都升级为新的类型。整数集合不支持降级操作,一旦对数组进行了升级,编码就会一直保持升级后的状态。
降级操作每次删除元素都需要判断所有元素是否可以降级,可能会影响性能,所以不支持?个人瞎猜的。
升级的好处
整数集合的升级策略有两个好处,一个是提升整数集合的灵活性,通过自动升级底层数组来适应新元素,可以随意地将int16_t、int32_t或者int64_t类型的整数添加到集合中,而不必担心出现类型错误,这种做法非常灵活。另一个是尽可能地节约内存。Redis作为内存数据库,内存空间也是十分宝贵的资源,整数集合优先使用小的类型来保存数据,升级操作只会在有需要的时候进行,这可以尽量节省内存。
参考
《Redis设计与实现》