Redis数据结构-整数集合

104 阅读2分钟
一、整数集合的底层实现
当集合中的元素都是整数值,并且元素的数量不多时,redis会使用整数集合作为集合键的底层实现。

typedef struct intset {
    // 编码方式
    uint32_t encoding;
    // 集合中的元素数量
    uint32_t length;
    // 保存元素的数组
    int8_t contents[];
} intset;
  • encoding:encoding属性的值可为INTSET_ENC_INT16、INTSET_ENC_INT32、INTSET_ENC_INT64
  • length:集合中元素的数量,即contents数组的长度
  • contents:集合中的每个元素是数组中的一项,并且按照从小到大依次排序,没有任何重复项;虽然contents声明为int8_t类型的数组,实际上数组的类型根据encoding的编码方式而定。

二、升级操作

当集合中添加一个新元素时,新元素的类型大小比当前集合中所有元素的类型都要大时,就需要先进行升级操作,才能将这个元素添加到集合中。升级的步骤如下:
  • 根据新元素的大小和元素的数量重新分配内存空间
  • 将现有集合中的元素放到正确的位置,保持有序性不变
  • 将新元素添加到新集合最后一个位置或第一个位置

三、升级的好处

  • 灵活性:因为c语言是静态类型的语言,所以整数数组中不能将不同类型的元素放在同一个集合中;所以有了自动升级操作,我们可以放心的将不同类型的元素放在同一个集合中
  • 节约内存:自动升级可以节约内存,根据实际情况逐步扩展所需的内存,而不用一开始都声明为int64类型的数组。

四、降级
整数集合不能进行降级操作,一旦对数组进行了升级,编码方式就一直保持为升级后的状态。

五、API
函数
作用
时间复杂度
intsetNew
创建一个新的整数集合
O(1)
intsetAdd
添加一个新元素
O(n)
intsetRemove
从集合中移除指定元素
O(n)
intsetFind
指定元素是否在集合中
O(logN)二分查找
intsetRandom
从集合中随机返回一个元素
O(1)
intsetGet
获得给定索引上的元素
O(1)
intsetLen
获得集合的长度
O(1)
intsetBlobLen
获得集合所占的内存字节数
O(1)