点击
蓝色
字体催更

前面讲到 数据结构集合 Sets 内部对应了两种编码格式:intset 和 hashtable。

关于 Redis 内部如何进行编码格式选择的简易流程图,如下:

如上述流程逻辑所示,当集合中所有的元素都为整数并且元素个数小于等于 set-max-intset-entries
设定的阈值时,使用 intset 编码格式进行集合的存储,反之,使用 hashtable 编码格式进行集合的存储。
总的来说影响集合编码选择的因素有两个:
集合元素类型
集合元素个数
一、操作验证集合编码选择流程
在 Redis 中一个数字字符串在数值在 [-9223372036854775808,9223372036854775807]/[-2^63,2^63-1] 内,才会以数值的格式存在,否则会被转为字符串
在试验前,将 set-max-intset-entries
阈值设为 5
## 查看当前 set-max-intset-entries 值127.0.0.1:6379> CONFIG GET set*1) "set-max-intset-entries"2) "512"## 临时设置 set-max-intest-entries = 5## 重启后失效127.0.0.1:6379> CONFIG set set-max-intset-entries 5OK## 查看临时设置后的 set-max-intset-entries127.0.0.1:6379> CONFIG GET set*1) "set-max-intset-entries"2) "5"
1.1、集合元素个数不超阈值下,元素为非整数
1.1.1、新增集合 set1
并增加一个整数元素
## 新增集合 `set1` 并增加一个整数元素127.0.0.1:6379> sadd set1 9223372036854775807(integer) 1## 集合编码格式为 intset127.0.0.1:6379> OBJECT encoding set1"intset"## 只有一个整数元素,元素个数 < set-max-intest-entries127.0.0.1:6379> SINTER set11) "9223372036854775807"
1.1.2、新增字符串元素
在 1.1.1 步骤后,新增字符串元素
## 在 1.1.1 步骤基础上,追加字符串元素127.0.0.1:6379> sadd set1 9223372036854775808(integer) 1## 此时 set1 元素个数2 < set-max-intset-entries127.0.0.1:6379> SINTER set11) "9223372036854775808"2) "9223372036854775807"## 由于存在字符串,不符合全部是整数的条件,所以编码格式为 hashtable127.0.0.1:6379> OBJECT encoding set1"hashtable"
1.2、元素都为整数的情况下,元素个数 > set-max-intset-entries
前面已经将
set-max-intset-entries
设置为 5
新增集合 set2 并初始化四个整数元素
## 新增集合 set2 ,并初始化五个整数元素127.0.0.1:6379> sadd set2 1 2 3 4 5(integer) 5## set2 集合元素127.0.0.1:6379> SINTER set21) "1"2) "2"3) "3"4) "4"5) "5"## 元素都为整数,元素个数5 = set-max-intset-entries ,所以为 intset127.0.0.1:6379> OBJECT encoding set2"intset"
新增一个整数元素,使得元素个数 > set-max-intset-entries
## 新增整数元素127.0.0.1:6379> sadd set2 6(integer) 1## 集合元素127.0.0.1:6379> SINTER set21) "4"2) "1"3) "3"4) "5"5) "2"6) "6"## 集合元素虽然都为整数,但是元素个数为 6 > set-max-intset-entries## 所以编码格式为 hashtable127.0.0.1:6379> OBJECT encoding set2"hashtable"
1.3、编码格式从intset到 hashtable 是不可逆的
在 1.2 的基础上进行验证,在 1.2 中的集合 set2 为
127.0.0.1:6379> SINTER set21) "4"2) "1"3) "3"4) "5"5) "2"6) "6"
元素都为整数 ,但是元素个数 > set-max-intset-entries
尝试从 set2 中 弹出一个数据,使得 set2 满足此时 intset 编码格式的要求(元素都为整数,且元素个数<= set-max-intset-entries)
## 从 set2 中移除一个元素127.0.0.1:6379> SPOP set2"6"## 元素个数5,全部为整数127.0.0.1:6379> SINTER set21) "4"2) "1"3) "3"4) "5"5) "2"## 编码格式不可逆127.0.0.1:6379> OBJECT encoding set2"hashtable"
二、源码角度看集合编码选择流程
以 t_set.c 的文件作为入口文件,以 sadd 的增加命令作为命令行 API 入口进行分析追踪,下面是 sadd 处理的时序图

c 中 long long 的取值范围为
[-9223372036854775808,9223372036854775807]
根据时序图,进行代码追踪,t_set.c#setTypeAdd
代码如下:

通过代码整理出新的编码选择流程图如下:

当集合元素个数小于等于 set-max-intset-entries
&& 元素都为 long long 类型的整数,则使用 intset 编码格式存储。
反之,使用 hashtable 编码格式存储集合数据。
【回复:Redis资料包】
获取相关 Redis 资料,资料实时更新....
end




