《Java后端知识体系》之Redis的整数集合底层实现

1.整数集合简述

整数集合是集合键的底层实现之一,当一个集合只包含整数值元素,并且这个集合的元素数量不多时,Redis就会使用整数集合作为集合键的底层实现。
例如当我们创建只包含五个元素的集合键,并且集合键中所有元素都是整数值,那么这个集合键的底层实现就会是整数集合:

redis>SADD  1 2 3 4 6
(integer) 5
reids>OBJECT ENCODING numbers
"intset"

2.整数集合的实现

整数集合是Redis用于保存整数值的集合抽象数据结构,它可以保存类型为int16_t、int32_t或者int64_t的整数值,并且保证集合中不会出现重复元素。
每个intset.h/intset结构标识一个整数集合:

typedef struct intset{
//编码方式
unit32_t encoding
//集合包含的元素数量
unit32_t length;
//保存元素的数组
int8_t contents[]
}intset;

contents数组是整数集合的底层实现:整数集合的每个元素都是contents数组的一个数组项(item),各个项在数组中按值的大小从小到大有序排列,并且数组中不包含任何重复项。
length属性记录了整数集合包含的元素数量,也是contents数组的长度。
contents数组的类型取决于encoding属性的值:
🔲如果encoding属性的值为INTSET_ENC_INT16,那么contents就是一个int16_t类型的数组,数组中的每个项都是int16_t类型的整数值(最小值为-32768,最大值为32767).
🔲如果encoding属性的值为INTSET_ENC_INT32,那么contents就是一个int32_t类型的数组,数组中的每个项都是int32_t类型的整数值.
🔲如果encoding属性的值为INTSET_ENC_INT64,那么contents就是一个int64_t类型的数组,数组中的每个项都是int64_t类型的整数值
下图中是一个encoding属性值为INTSET_ENC_INT16的整数集合,该集合中保存的都是int16_t类型的整数值。
在这里插入图片描述

当向一个底层为int16_t数组的整数集合中添加一个int64_t类型的整数值时,整数集合中已有的所有元素都会被转换为int64_t类型,这就涉及到整数集合的升级。

3.升级

当我们将新元素添加到整数集合里面时,并且新元素的类型比整数集合现有的元素类型都要长时,整数集合需要先进行升级,然后才能将新元素添加到整数集合中。
升级整数集合并添加新元素共分为三步:

  1. 根据新元素的类型,扩展整数集合底层数组的空间大小,并未新元素分配空间。
  2. 将底层数组现有的所有元素都转换为与新元素相同的类型。并将类型转换后的元素放到正确的位置上,并且在防止元素过程中需要位置底层数组的有序性不变。
  3. 将新元素添加到底层数组里面。
    例如我们将65432添加到上图中的整数集合中,,因为65432的类型是int32_t,所以将该值添加到整数集合前需要对整数升级,升级首先要做的就是根据新类型的长度以及元素的数量,对底层数组进行空间分配,
    也就是需要对上图中的元素进行重新分配空间,可以看到上图中有五个元素,再加上65432新元素也就是有六个元素,每个元素的整数值(类型是int32_t)都是占用32位空间,所以底层数组大小应该为32*6=192位。
    重新分配空间后前五位仍然是16位,所以需要对这16位重新分配,分配过程如下图:
    在这里插入图片描述

最终将所有的数据都分配成占32位的元素。

4.升级好处

整数集合升级策略有两个好处:
• 提升整数集合的灵活性:这是因为C语言是静态类型语言,为了避免类型错误,通常不会将两种不同类型的值放到同一个数据结构里面。
• 尽可能节约内存:如果我们直接将数组的内存设置位int64_t,这样就能保存任一一种类型的整数,但是数组会分配int64_t内存去保存int16_t类型的数据,造成浪费内存的情况。

5.降级

整数集合不支持降级操作,一旦对数组进行升级,编码就会一直保持升级后的状态。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值