《Redis设计与实现》[整数集合]章节笔记

本文深入探讨了Redis中整数集合(intset)的内部机制,包括其定义、编码方式、数据存储特点及自动升级原理,解释了为何在特定条件下使用intset能更有效地节省内存。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

1、什么是整数集合?

整数集合(intset)是集合键的底层实现之一,是 Redis 用于保存整数值的集合抽象数据结构。

(集合对象(set)的编码可以是 intset 或者 hashtable )

2、既然集合对象set底层有2种数据结构实现,那么什么时候用整数集合呢?

当集合对象可以同时满足以下两个条件时, 对象使用 intset 编码:

  1. 集合对象保存的所有元素都是整数值;
  2. 集合对象保存的元素数量不超过 512 个;(这个512是可以通过配置文件修改的,不用记)

不能满足这两个条件的集合对象需要使用 hashtable 编码(底层转换,把intset种的数据转移到hashtable里)。

3、这个数据结构的定义是什么样的?

typedef struct intset {
    uint32_t encoding;    // 编码方式
    uint32_t length;      // 元素数量,即 contents 数组的长度
    int8_t contents[];    // 保存元素的数组
} intset;

4、编码方式encoding是什么意思?为什么一个数据结构会有这么个属性呢?

 encoding 属性的值可以是 INTSET_ENC_INT16、INTSET_ENC_INT32、INTSET_ENC_INT64

一句话总结:intset可以存储 int16、int32、int64 这3种类型的数据。至于具体存的是哪个类型,又encoding指定。

5、可是明明 contents[]指定的类型是int8啊?怎么存int16、int32、int64啊?

原文:

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

原文并没有讲原因,以下是我的理解:

类比Go的string类型,底层是[]byte。存int16就用2个int8表示就行呗,int8这里可以看成一个单位。

6、contents里的数据有没有排序?有的话什么顺序?

contents 数组按从小到大的顺序保存着集合中的元素。

7、Redis中的set类型无序且不重复,为啥contents要排序?

数组 + 有序排列,你想到了什么?

举例一个set的用法,类似编程语言中的某些集合的 contains() 方法。

SISMEMBER key member :判断 member 元素是否集合 key 的成员(人话就是member是否包含在这个set中)

8、可是我还是不明白为什么一个破数组要分那么多类型存储?

你用mysql一个varchar(4000)存性别字段,有问题么?除了别人会骂你脑瘫,严格意义上问题不大。

但是redis不行。redis基于内存,内存很贵,内存有限。坦白讲:不管大数小数都用int64存其实没什么问题。

所以你会在书中多次看到这几个字:节省内存。

这也是为什么redis底层用了这么多数据结构的原因,也许很多API也许不是时间复杂度最低的,但是他一定要找到一个时间复杂度和空间复杂度的平衡。毕竟基于内存,没办法追求极致的处理速度。

9、那你这么说,原来都是int16的值,突然插入一个int32的咋办?

专业名词:升级

原文:

每当我们要将一个新元素添加到整数集合里面, 并且新元素的类型比整数集合现有所有元素的类型都要长时,

整数集合需要先进行升级(upgrade), 然后才能将新元素添加到整数集合里面。

10、咋升级?

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

11、既然有升级,那有降级么?

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

12、说了那么多,为什么要存在这种数据结构,有什么好处?

尽可能地节约内存。

因为整数集合可以通过自动升级底层数组来适应新元素, 所以我们可以随意地将 int16_t 、 int32_t 或者 int64_t 类型的整数添加到集合中, 而不必担心出现类型错误, 这种做法非常灵活。

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

13、集合对象保存的元素数量不超过 512 个,为什么要有这个限制?为什么是512?

效率问题,redis作者一定有自己的考量,intset有可取之处,但是不能解决大量数据的问题,显然数据量大用hashtable更好。

为什么是512,笔者猜测,干程序的就愿意整一些128啊 256啊这类的数,怎么地?513就一定效率低么,所以你也不用记。

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值