整数集合intset
整数集合的定义
Redis 中的整数集合 intset 是用来保存多个不重复的整数值且有序的集合抽象数据结构,可以保存类型为 int16-t 、int32-t 或者 int64-t 的整数值。它是实现集合键底层之一。
整数集合应用场景
整数集合在 Redis 中作为了集合 Set 数据结构的底层实现之一。
当一个集合中的元素都是整数值,且元素不多的时候,整数集合就会作为集合 Set 的底层实现。
举个例子:如果我们创建一个只包含五个元素的集合键,并且集合中的所有元素都是整数值,那么这个集合键的底层实现就会是整数集合:
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数组的长度。
- encoding属性,决定数组contents存储元素的真正类型。
- INTSET_ENC_INT16:int16_t类型的整数值(最小值为32768,最大值为32767)
- INTSET_ENC_INT32:int32_t类型的整数值(最小值为2147483648,最大值为2147483647)
- INTSET_ENC_INT64:个int64_t类型的整数值(最小值为9223372036854775808,最大值为9223372036854775807)
整数集合的结构:
如图6-1:一个包含5个int16_t类型整数数值的整数集合:contents数组的大小等于sizeof(int16_t)*5=16*5=80位。
如图6-2:一个包含4个int64_t类型整数数值的整数集合:contents数组的大小等于sizeof(int64_t)*4=64*4=256位。
插入元素操作:
- 插入元素的时候,会先计算新元素所需的长度,然后if 判断是否需要升级操作。
- 如果新元素的编码类型比原来整数集合的 encoding 值大,那么进行集合升级操作,之后将升级后的整数集合返回。
- 不满足升级操作的话,先查找新元素是否在原来的整数集合存在,
- 存在,操作失败,返回原来的整数集合。这里是为了保证整数集合的元素唯一性。
- 不存在,就会为集合调整新的内存空间,然后将新元素设置进他合适的位置上。
- 之后为 length 属性值加一,返回新的整数集合,完成了插入操作。
查找元素操作:
- 查找元素开始的时候,先对整数集合是否有值进行判断,没值就返回0。
- 有值就通过获取首尾元素的值来判断该元素是否存在集合中,因为整数集合的有序性,通过最大最小值可以直接判断出是否存在。
- 然后通过数组的二分查找思想的代码,快速查找该元素的位置,最终找到了位置就返回1表示找到并将找到的位置设置到 pos 属性,0表示没找到。
删除元素操作:
- 先计算需要删除元素的编码类型,只有当元素的编码类型小于等于整数集合的 encoding 的时候在进行下一步,(因为大于的话,表示该元素不存在整数集合中);
- 且调用 intsetSearch 函数查找元素存在,存在才执行具体的删除操作。
- 具体删除操作的时候,调用 intsetMoveTail 函数将原来这个元素的位置后面的元素往前移动。
- 最后重新调整集合的内存空间,以及集合的长度完成了最终的删除操作。
升级
每当向集合添加元素的时候,如果新元素的类型比enconding属性的类型长时,需要先对整个整数集合需要进行升级,然后把新元素添加进来。
升级操作步骤:时间复杂度为O(N)
- 根据新元素的类型,扩展整数集合底层数组的空间大小,并为新元素分配空间。
- 将底层数组现有的所有元素都转换成与新元素相同的类型,并将类型转换后的元素放置到正确的位上,而且在放置元素的过程中,需要继续维持底层数组的有序性质不变。
- 将新元素添加到底层数组里面。
- 将enconding改为当前类型,长度加一。
升级过程案例:
(1)一个包含三个int16_t类型的整数集合,整数集合底层数组的大小为3*16=48位。
(2)添加一个新元素65535,类型是int32_t的>int16_t,进行升级。
先进行空间重分配;分配的空间大小是= 4*32 - 3*16= 128 - 48 = 80位;
在对倒数第3个元素进行类型转换;
在对倒数第2个元素进行类型转换;
在对倒数第1个元素进行类型转换;
类型转换完成后,将新元素添加到尾部;
最后,程序将整数集合encoding属性的值从INTSET_ENC_INT16改为INTSET_ENC_INT32,并将length属性的值从3改为4;
升级之后新元素的摆放位置
因为引发升级的新元素的长度总是比整数集合现有所有元素的长度都大,所以这个新元素的值要么就大于所有现有元素,要么就小于所有现有元素:
- 在新元素小于所有现有元素的情况下,新元素会被放置在底层数组的最开头(索引0);
- 在新元素大于所有现有元素的情况下,新元素会被放置在底层数组的最末尾(索引length1)。
升级的好处
整数集合的升级策略有两个好处,一个是提升整数集合的灵活性,另一个是尽可能地节约内存。
(1)提升灵活性
因为整数集合可以通过自动升级底层数组来添加元素,所以可以任意添加不同类型的数值(int16_t,int32_t,int64_t),不必担心类型错误。
(2)尽可能的节约内存
不必上来就定义int64_t类型(或者更长的类型)的数组,而是在需要的时候在扩展为int64_t(或者更长的类型);
降级-不支持
整数集合不支持降级操作,一旦对数组进行了升级,编码就会一直保持升级后的状态。
总结
- 整数集合是集合键的底层实现之一。
- 整数集合的底层实现为数组,这个数组以有序、无重复的方式保存集合元素,在有需要时,程序会根据新添加元素的类型,改变这个数组的类型。
- 升级操作为整数集合带来了操作上的灵活性,并且尽可能地节约了内存。
- 整数集合只支持升级操作,不支持降级操作。
黄健宏 著. Redis设计与实现 (Chinese Edition) (Kindle 位置 938-940). Kindle 版本.
整数集合intset相关推荐
- Redis之整数集合intset
intset是Redis集合的底层实现之一,当存储整数集合并且数据量较小的情况下Redis会使用intset作为set的底层实现.当数据量较大或者集合元素为字符串时则会使用dict实现set. int ...
- Redis数据结构——整数集合-intset
整数集合 整数集合是集合键的底层实现之一,当一个集合只包含整数值元素,并且这个集合的元素数量不多时,Redis就会使用整数集合作为集合键的底层实现. 1.整数集合实现: 整数集合是redis用于保存整 ...
- Redis学习之intset整数集合源码分析
1.整数集合:整数的集合,升序排序,无重复元素 2.整数集合intset是集合键的底层实现之一,当一个集合只包含整数值的元素,并且这个集合的元素数量不多时,redis会使用整数集合作为集合键的底层实现 ...
- Redis之intset(整数集合)
Redis中set数据结构它是由intset或者hashtable构成的今天我们就来讲一下intset 整数集合(intset)呢, 是一个有序的存储数据的结构 它有以下优点 1.整数集合中, 元素按 ...
- 数据结构与算法:13 字符串与整数集合
13 字符串与整数集合 知识点: 1. 字符串 我们古人没有电影电视,没有游戏网络,所以文人们就会想出一些文字游戏来娱乐.比如宋代的李禺写了这样一首诗:"枯眼望遥山隔水,往来曾见几心知?壶空 ...
- [redis设计与实现][5]基本数据结构——整数集合
整数集合(intset)用于集合键.当一个集合只包含整数值元素,并且数量不多的时候,会使用整数集合作为集合键的底层实现.相对于直接保存字符串,整数集合能够很好地节约内存,但是由于是数组保存,需要特别关 ...
- Redis源码剖析(十三)整数集合
Redis提供一种叫整数集合的数据结构,当数据中只包含整数,并且数据数量不多时,Redis便会采用整数集合存储 Redis保证整数集合有以下几个特性 所含元素全是整数,且不重复 内部元素有序,通常是会 ...
- Redis的设计与实现之整数集合和压缩列表
整数集合(intset) 整数集合概念 整数集合是一个集合(set) 整数集合里只包含整数,并且集合元素不能太多 整数集合不会有重复的元素(有重复元素集合就没意义了) 整数集合的实现方式 typede ...
- Redis 数据结构 :SDS、链表、字典、跳表、整数集合、压缩列表
文章目录 SDS 结构分析 内存策略 空间预分配 惰性空间释放 总结 链表 结构分析 总结 字典 结构分析 rehash 渐进式rehash 总结 跳表 结构分析 总结 整数集合 结构分析 升级 降级 ...
最新文章
- (转自PHPer)成长的选择
- c++ 导入caffe
- python 判断时间是否大于6点_48 python判断时间是否落在两个时区之间(只比较时刻不比较日期)...
- java基础---多线程之交替打印,等待唤醒机制
- BZOJ_1009_[HNOI2008]_GT考试_(动态规划+kmp+矩阵乘法优化+快速幂)
- python2编码问题解决了吗_Python2编码问题
- Website English Comments
- 看大厂NLP的面试经验之后的一些思考总结
- python数据挖掘学习路线
- 免费rar密码破解工具排行榜
- 简单批处理内部命令简介
- 如何用ps设计出一张吸引人眼球的创意节日海报?
- GoogleMap获取地图中心点位置信息
- 信息发布类网站后台界面设计一点思考(整体布局)
- 其他品牌的触控笔能用在ipad上?性价比高的触控笔合集
- 错误使用 load ASCII 文件的行号 1 中的文本未知“MATLAB“。
- 江西专升本考试作弊事件,为什么最近考试作弊事件频发?
- java判断标签闭合_html转PDF(java)非常奇怪的错误,标签没闭合
- 怀旧软件_如何将怀旧的嘶嘶声和黑胶唱片的流行音乐添加到MP3文件
- 累计投放贷款1000亿,马云是如何做银行的?