Set
Set 是 Redis 中的单列集合,满足下列特点:
- 不保证有序性
- 保证元素唯一(可以判断元素是否存在)求交集、并集、差集
HashTable,也就是 Redis 中的 Dict,不过 Dict 是双列集合(可以存键、值对)
Set 是 Redis 中的集合,不一定确保元素有序,可以满足元素唯一、查询效率要求极高。
- 为了查询效率和唯一性,set 采用 HT 编码(Dict)。Dict 中的 key 用来存储元素,value 统一为 null。
- 当存储的所有数据都是整数,并且元素数量不超过 set-max-intset-entries 时,Set 会采用 IntSet 编码,以节省内存。
判断是不是整数,如果是用 intset 编码,否则用 dict
添加数据的逻辑,还是挺清晰的
intset 内存图
dict 内存图
intset
结构
IntSet 是 Redis 中 set 集合的一种实现方式,基于整数数组来实现,并且具备长度可变、有序等特征。
encoding 包含三种模式,表示存储的整数大小不同
为了方便查找,Redis 会将 intset 中所有的整数按照升序依次保存在 contents 数组中,结构如图:
现在,数组中每个数字都在 int16_t 的范围内,因此采用的编码方式是 INTSET_ENC_INT16,每部分占用的字节大小为:
- encoding:4字节
- length:4字节
- contents:2字节*3 = 6字节
为什么需要保存 encoding 大小
因为可以通过下面的公式通过 index 快速找到目标地址
扩容
我们向该其中添加一个数字:50000,这个数字超出了 int16_t 的范围,intset 会自动升级编码方式到合适的大小。以当前案例来说流程如下:
源码
插入函数,判断当前编码值和需要插入的元素的编码值
如果新元素是大于零的,从后开始搬运后插入最后一个位置,否则插入第一个位置
通过二分查找查看是否需要插入