整数集合
整数集合(intset)是集合键的底层实现之一。当集合只包含整数值元素,并且元素数量不多,Redis就会使用整数集合作为集合键的底层实现。
1. 整数集合的实现
Redis用于保存整数值的集合抽象数据结构。保存的类型为:int16_t、int32_t或者int64_t 的整数值,并且保存集合中不出现重复元素。
intset集合结构:
typedef struct intset{
// 编码方式
uint32_t encoding;
// 集合包含的元素数量
uint32_t length;
// 保存元素的数组
int8_t contents[];
}intset;
contents 数组是整数集合的底层实现,每个元素都是contents数组的一个数组项(item),数组中按值的大小从小到大有序的排列,且数组中不包含重复项。
**注:**数组虽然为int8_t类型,但是保存数据的类型,由encoding属性值决定。
length 记录了集合中包含的元素数量,是contents数组的长度。
encoding 属性:
(1) INTSET_ENC_INT16类型,contents就是一个int16_t类型的数组,每项都是一个int16_t类型的整数值(-32768~32767)。
(2) INTSET_ENC_INT32类型,contents就是一个int32_t类型的数组,每项都是一个int32_t类型的整数值(-2147483648~2147483647)。
(3) INTSET_ENC_INT64类型,contents就是一个int64_t类型的数组,每项都是一个int64_t类型的整数值(-9223372036854775808~9223372036854775807)。
encoding 属性值为INTSET_ENC_INT16,则保存的是int16_t类型的数值。contents数组按从小到大的顺序保存四个元素,length属性为4。contents数组的大小为 sizeof(int16_t) * 4 = 16 * 4 = 64位(bit)。
contents数组保存数据的规则:当底层为int16_t数组的整数集合添加一个int64_t类型的整数值时,那么集合中已有的元素都会被转换成int64_t类型。
2. 升级
当新添加的元素比整数集合现有的所有元素都要长的时候,证书集合需要先进行升级(upgrade),然后才能将新元素添加到整数集合中。
整数集合的升级步骤:
- 根据新元素类型,扩展整数集合底层数组的大小,为新元素分配空间。
- 将现有元素类型转换成新元素相同类型,并将转换后的元素放到对应位置。放置元素的过程中,维持底层数组的有序性不变。
- 将新添元素添加到整数集合数组中。
**注:**升级首先做的是,根据新元素类型的长度,以及集合元素的数量(包含新增),对底层数组空间重分配。

3. 升级的好处
提升整数集合的灵活性;尽可能地节约内存。
3.1 提升灵活性
因为C语言是静态类型语言的特点,避免错误,通常不会把两种不同类型的值放在同一个数据结构里。
3.2 节约内存
若让一个数组同时保存int16_t、int32_t、int64_t三种类型的值,最简单的方法就是使用int64_t类型的数组作为整数集合数组的底层实现。同时,如果保存的是int16_t类型的元素,则数组都需要使用int64_t类型的空间保存,则会造成内存浪费。整数集合的做法满足了同时保存三种不同类型值的需求,也可以在有需要的时候进行。
4. 降级
整数集合不支持降级操作,升级过后,则一直保持在升级后的状态。