图解redis之整数集合
创始人
2025-05-30 09:17:10
0

引言:

整数集合(intset)是集合键的底层实现之一,当一个集合只包含整 数值元素,并且这个集合的元素数量不多时,Redis就会使用整数集合 作为集合键的底层实现。

举个例子,如果我们创建一个只包含五个元素的集合键,并且集合 中的所有元素都是整数值,那么这个集合键的底层实现就会是整数集合

redis> SADD numbers 1 3 5 7 9
(integer) 5
redis> OBJECT ENCODING numbers
"intset"

整数集合

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

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

解析:

contents数组是整数集合的底层实现:整数集合的每个元素都是 contents数组的一个数组项(item),各个项在数组中按值的大小从小到 大有序地排列,并且数组中不包含任何重复项。

length属性记录了整数集合包含的元素数量,也即是contents数组的 长度。

虽然intset结构将contents属性声明为int8_t类型的数组,但实际上 contents数组并不保存任何int8_t类型的值,contents数组的真正类型取决 于encoding属性的值

·如果encoding属性的值为INTSET_ENC_INT16,那么contents就是 一个int16_t类型的数组,数组里的每个项都是一个int16_t类型的整数值 (最小值为-32768,最大值为32767)。

·如果encoding属性的值为INTSET_ENC_INT32,那么contents就是 一个int32_t类型的数组,数组里的每个项都是一个int32_t类型的整数值 (最小值为-2147483648,最大值为2147483647)。 ·

如果encoding属性的值为INTSET_ENC_INT64,那么contents就是 一个int64_t类型的数组,数组里的每个项都是一个int64_t类型的整数值 (最小值为-9223372036854775808,最大值为 9223372036854775807)

举例一

 ·encoding属性的值为INTSET_ENC_INT16,表示整数集合的底层实 现为int16_t类型的数组,而集合保存的都是int16_t类型的整数值。

·length属性的值为5,表示整数集合包含五个元素。

·contents数组按从小到大的顺序保存着集合中的五个元素。 ·因为每个集合元素都是int16_t类型的整数值,所以contents数组的 大小等于sizeof(int16_t)*5=16*5=80位

举例二:

 ·encoding属性的值为INTSET_ENC_INT64,表示整数集合的底层实 现为int64_t类型的数组,而数组中保存的都是int64_t类型的整数值。

·length属性的值为4,表示整数集合包含四个元素。

·contents数组按从小到大的顺序保存着集合中的四个元素。 ·因为每个集合元素都是int64_t类型的整数值,所以contents数组的 大小为sizeof(int64_t)*4=64*4=256位。

虽然contents数组保存的四个整数值中,只有-2675256175807981027 是真正需要用int64_t类型来保存的,而其他的1、3、5三个值都可以用 int16_t类型来保存,不过根据整数集合的升级规则,当向一个底层为 int16_t数组的整数集合添加一个int64_t类型的整数值时,整数集合已有 的所有元素都会被转换成int64_t类型,所以contents数组保存的四个整数 值都是int64_t类型的,不仅仅是-2675256175807981027

升级

每当我们要将一个新元素添加到整数集合里面,并且新元素的类型 比整数集合现有所有元素的类型都要长时,整数集合需要先进行升级 (upgrade),然后才能将新元素添加到整数集合里面

升级整数集合并添加新元素共分为三步进行:

1)根据新元素的类型,扩展整数集合底层数组的空间大小,并为 新元素分配空间。

2)将底层数组现有的所有元素都转换成与新元素相同的类型,并 将类型转换后的元素放置到正确的位上,而且在放置元素的过程中,需 要继续维持底层数组的有序性质不变。

3)将新元素添加到底层数组里面

举个例子,假设现在有一个INTSET_ENC_INT16编码的整数集合, 集合中包含三个int16_t类型的元素

 因为每个元素都占用16位空间,所以整数集合底层数组的大小为 3*16=48位

 现在,假设我们要将类型为int32_t的整数值65535添加到整数集合 里面,

因为65535的类型int32_t比整数集合当前所有元素的类型都要 长,所以在将65535添加到整数集合之前,程序需要先对整数集合进行 升级。 升级首先要做的是,根据新类型的长度,以及集合元素的数量(包 括要添加的新元素在内),对底层数组进行空间重分配。

整数集合目前有三个元素,再加上新元素65535,整数集合需要分 配四个元素的空间,因为每个int32_t整数值需要占用32位空间,所以在 空间重分配之后,底层数组的大小将是32*4=128位,。

下图所示 虽然程序对底层数组进行了空间重分配,但数组原有的三个元素1、2、3 仍然是int16_t类型,这些元素还保存在数组的前48位里面,所以程序接 下来要做的就是将这三个元素转换成int32_t类型,并将转换后的元素放 置到正确的位上面,而且在放置元素的过程中,需要维持底层数组的有 序性质不变

 首先,因为元素3在1、2、3、65535四个元素中排名第三,所以它 将被移动到contents数组的索引2位置上,也即是数组64位至95位的空间内

 接着,因为元素2在1、2、3、65535四个元素中排名第二,所以它 将被移动到contents数组的索引1位置上,也即是数组的32位至63位的空 间内

 之后,因为元素1在1、2、3、65535四个元素中排名第一,所以它 将被移动到contents数组的索引0位置上,即数组的0位至31位的空间内

 然后,因为元素65535在1、2、3、65535四个元素中排名第四,所 以它将被添加到contents数组的索引3位置上,也即是数组的96位至127 位的空间内

 最后,程序将整数集合encoding属性的值从INTSET_ENC_INT16改 为INTSET_ENC_INT32,并将length属性的值从3改为4,设置完成之后 的整数集合

 因为每次向整数集合添加新元素都可能会引起升级,而每次升级都 需要对底层数组中已有的所有元素进行类型转换,所以向整数集合添加 新元素的时间复杂度为O(N)

优点:

1.提升灵活性:

因为C语言是静态类型语言,为了避免类型错误,我们通常不会将 两种不同类型的值放在同一个数据结构里面

2.节约内存

当然,要让一个数组可以同时保存int16_t、int32_t、int64_t三种类 型的值,最简单的做法就是直接使用int64_t类型的数组作为整数集合的 底层实现。不过这样一来,即使添加到整数集合里面的都是int16_t类型 或者int32_t类型的值,数组都需要使用int64_t类型的空间去保存它们, 从而出现浪费内存的情况。

而整数集合现在的做法既可以让集合能同时保存三种不同类型的 值,又可以确保升级操作只会在有需要的时候进行,这可以尽量节省内 存

降级

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

举个例子,对于下图所示的整数集合来说,即使我们将集合里唯 一一个真正需要使用int64_t类型来保存的元素4294967295删除了,整数 集合的编码仍然会维持INTSET_ENC_INT64,底层数组也仍然会是 int64_t类型的

删除之后 

 

 

相关内容

热门资讯

路透解析“马斯克集团”:Spa... SpaceX 凤凰网科技讯 北京时间1月31日,据路透社报道,长期以来,埃隆·马斯克(Elon Mu...
启动“二改” 永辉在京完成21... 北京商报讯(记者 赵述评 实习记者 毛思怡)1月31日,永辉超市北京龙湖长楹天街店经一个多月闭店调改...
《宜宾散装白酒连锁经营规范》团... 近日,由宜宾市酒类协会牵头归口、宜宾安宁酒厂主导起草,四川谊宾酒业、宜宾学院、劲牌南溪酒业等多家本地...
印度牙医博士打造全印首款人形机... 2026 年 1 月 23 日,印度浦那的 Muks Robotics 正式宣布,自主研发的社交人形...
金银价创新高,引发全球“贵金属... 【环球时报记者 倪浩 环球时报特约记者 甄翔】连日来,国际市场金银价格持续大涨。1月29日当天,亚太...
财经观察丨“爱你老己”背后的消... 新华网北京1月31日电岁末年初,一句“爱你老己,明天见”席卷社交网络,成为年轻人自我关怀的新表达。热...
重磅!珠海科技产业集团与农行广... 1月30日,珠海科技产业集团与中国农业银行广东省分行在广州签署全面战略合作协议暨独立授信合作。农行广...
原创 黄... 谁能想到,2026年开年就上演金融魔幻现实主义! 国际黄金1月31日凌晨暴跌9.25%,盘中狂泻12...
云南省本级社会保险基金银行存款... 近日,云南省财政厅、云南省人力资源和社会保障厅、云南省医疗保障局联合印发《云南省本级社会保险基金银行...
病毒在身体里“安家”却相安无事... 很多人听说“乙肝携带者”,总会下意识和“乙肝患者”画上等号,担心自己或身边人被传染,也害怕携带者最终...
库迪确认:取消全场9.9元 来源:滚动播报 (来源:新消费日报) 有消息称,库迪咖啡发布门店价格策略和活动调整通知。通知指出,...
原创 雷... 不知道大家有没有发现,这个周六可能是进入2026年之后最消停的一个周六。因为各品牌基本上都没什么大事...
原创 特... 特朗普对委内瑞拉的举动,表面上看是一场能源棋局,实则背后隐藏着深刻的战略考量。对他而言,掌握能源就意...
原创 李... 01、“私募魔女”李蓓再引争议 半夏投资创始人、“私募魔女”李蓓,最近又成为投资圈的焦点。 1月2...
爱美客:AestheFill产... 上证报中国证券网讯(记者 王子霖)备受医美行业瞩目的AestheFill产品独家经销权纠纷迎来重要进...
雷军明晚直播,在北京小米汽车工... IT之家 1 月 31 日消息,今天午间,小米创办人、董事长兼 CEO 雷军在微博发文宣布,2 月 ...
字节阿里DeepSeek决战春... 新智元报道 编辑:艾伦 【新智元导读】这个春节,中国 AI 迎来「决战时刻」。据《The Info...
皇台酒业开始过年? 富凯摘要:有钱没钱喝酒过年。 作者|欧文 1月30日,白酒板块再现分化行情,皇台酒业却延续强势表现,...
深交所修订可持续发展报告编制指... 上证报中国证券网讯 据深交所1月30日消息,深交所发布实施《深圳证券交易所上市公司自律监管指南第3号...
面试餐饮|新手零经验,小红书开... 有没有餐饮人跟我一样?想靠小红书引流拓客,却卡在第一步:不知道怎么开店、怎么发笔记不踩雷,看着别人的...