Redis Set是一种无序的、不重复的字符串集合,它提供了很多方便的操作,比如添加、删除、判断是否存在、求交集、并集、差集等。但是,你知道Redis Set是如何在底层实现的吗?本文将从源码的角度,分析Redis Set的内部结构和优化技巧。
Redis Set的内部结构
Redis Set的内部结构有两种,一种是intset,另一种是hashtable。它们的区别在于存储的元素类型和数量。
intset是一种紧凑的整数集合,它用一个连续的内存空间来存储多个整数值,并且保证这些值是有序且不重复的。intset的结构如下:
// 编码方式
// 集合包含的元素数量
// 保存元素的数组
其中,encoding字段表示元素的编码方式,它决定了contents数组中每个元素占用的字节数,以及能够存储的最大值。目前,Redis支持3种编码方式:
1.INTSET_ENC_INT16:每个元素占用2个字节,范围为[-215, 215-1]。
2.INTSET_ENC_INT32:每个元素占用4个字节,范围为[-231, 231-1]。
3.INTSET_ENC_INT64:每个元素占用8个字节,范围为[-263, 263-1]。
length字段表示集合中元素的数量,它决定了contents数组的长度。contents数组是一个变长数组,它根据encoding和length动态分配空间,并且按照从小到大的顺序存储元素。
hashtable是一种哈希表结构,它用一个散列表来存储任意类型的字符串,并且保证这些字符串是不重复的。hashtable的结构如下:
// 哈希表
// 当前正在运行的安全迭代器数量
// 哈希表数组
// 哈希表大小
// 哈希表大小掩码,用于计算索引值
// 该哈希表已有节点的数量
// 指向下个哈希表节点,形成链表
其中,dict结构表示一个哈希表对象,它包含两个dictht结构(ht[0]和ht),分别表示两个哈希表。通常情况下,只有ht[0]被使用,ht只在进行rehash时才会用到。rehashidx表示当前正在进行rehash的索引,如果为-1,表示没有在进行rehash。iterators表示当前正在运行的安全迭代器的数量,如果不为0,表示不能进行rehash。
dictht结构表示一个哈希表,它包含一个dictEntry指针数组(table),用来存储键值对。size表示哈希表的大小,即table数组的长度,它必须是2的幂。sizemask表示哈希表的大小掩码,即size-1,它用来计算键的哈希值对应的索引值。used表示哈希表已有节点的数量,即table数组中非空元素的个数。
dictEntry结构表示一个哈希表节点,它包含一个键(key)和一个值(v)。值可以是一个指针(val),也可以是一个64位的整数(u64或s64),或者是一个双精度浮点数(d)。next指针指向下一个哈希表节点,形成一个链表,用来解决哈希冲突。
Redis Set的优化技巧
Redis Set在底层使用了两种不同的结构来存储集合数据,这是为了在不同的场景下提高空间和时间效率。具体来说,Redis Set遵循以下规则:
1.当集合中只包含整数值,并且元素数量不超过512个时,使用intset结构。
2.当集合中包含非整数值,或者元素数量超过512个时,使用hashtable结构。
这样做的好处是:
1.intset结构比hashtable结构更节省空间,因为它没有额外的指针和哈希表开销,并且可以根据元素的大小动态调整编码方式。
2.intset结构比hashtable结构更快速,因为它可以利用二分查找来定位元素,并且没有哈希冲突和链表遍历的问题。
3.hashtable结构比intset结构更灵活,因为它可以存储任意类型的字符串,并且可以容纳更多的元素。
当集合的类型和大小发生变化时,Redis Set会自动地在intset和hashtable之间进行转换,以保证最佳的性能。例如:
1.当向一个空集合添加一个整数值时,Redis Set会创建一个intset结构,并将该值添加到其中。
2.当向一个intset结构的集合添加一个非整数值时,Redis Set会创建一个hashtable结构,并将原来的intset结构中的所有元素以及新添加的元素复制到其中,然后释放原来的intset结构。
3.当向一个intset结构的集合添加一个整数值时,如果该值超过了当前编码方式所能表示的范围,Redis Set会升级编码方式,并将原来的所有元素以及新添加的元素重新编码到新的intset结构中。
4.当从一个hashtable结构的集合删除一个元素时,如果该集合中只剩下整数值,并且元素数量小于等于512个,Redis Set会创建一个intset结构,并将原来的hashtable结构中的所有元素复制到其中,然后释放原来的hashtable结构。