暂无图片
暂无图片
暂无图片
暂无图片
暂无图片

【019】-Redis-数据结构-set-编码格式及编码选择

花好夜猿 2020-10-19
1519

点击

蓝色

字体催更


前面讲到 数据结构集合 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 5
OK


## 查看临时设置后的 set-max-intset-entries
127.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


## 集合编码格式为 intset
127.0.0.1:6379> OBJECT encoding set1
"intset"


## 只有一个整数元素,元素个数 < set-max-intest-entries
127.0.0.1:6379> SINTER set1
1) "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-entries
127.0.0.1:6379> SINTER set1
1) "9223372036854775808"
2) "9223372036854775807"


## 由于存在字符串,不符合全部是整数的条件,所以编码格式为 hashtable
127.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 set2
1) "1"
2) "2"
3) "3"
4) "4"
5) "5"


## 元素都为整数,元素个数5 = set-max-intset-entries ,所以为 intset
127.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 set2
1) "4"
2) "1"
3) "3"
4) "5"
5) "2"
6) "6"


## 集合元素虽然都为整数,但是元素个数为 6 > set-max-intset-entries
## 所以编码格式为 hashtable
127.0.0.1:6379> OBJECT encoding set2
"hashtable"

1.3、编码格式从intset到 hashtable 是不可逆的

在 1.2 的基础上进行验证,在 1.2 中的集合 set2 为

127.0.0.1:6379> SINTER set2
1) "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 set2
1) "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


2:表示 quicklist 两端各有2个 quicklist node 节点不压缩,中间的其他 quicklist 节点进行压缩


文章转载自花好夜猿,如果涉嫌侵权,请发送邮件至:contact@modb.pro进行举报,并提供相关证据,一经查实,墨天轮将立刻删除相关内容。

评论