Redis 集合(set)实现(4)

set基本介绍

Redis里的set结构类似于java里的HashSet,实现上基本相同,它包含的元素无序,且不能重复,Redis里的set结构还实现了基础的集合并、交、差的操作。hashSet底层是hashMap现的,value存的是一个object对象。redis set底层实现为了节省内存随着元素类型是否是整型以及添加的元素的数目多少,而有所变化。概括来讲,当set中添加的元素都是整型且元素数目较少时,set使用intset作为底层数据结构,否则,set使用dict作为底层数据结构。

那什么情况下redis set集合底层会从intset变为 dict?

	set-max-intset-entries 512

当set元素个数为全整数,整数范围在-2^{64}~2^{64}-1(后续会讲到为什么是这个范围) 且元素的个数少于512个时底层为intset,否则转换为dict

通过前几篇的学习我们知道目前用到dict的地方有 k-v映射、有序集合底层用来实现值和分数的映射、散列表、还有今天要讲的set结构。 dict的实现我们在前文已经详细的介绍过了这里就不在废话了,对字典不太熟悉的同学可以查看redis字典实现


intset数据结构简介

intset顾名思义,是由整数组成的集合。实际上,intset是一个由整数组成的有序集合,从而便于在上面进行二分查找,用于快速地判断一个元素是否属于这个集合。它在内存分配上与ziplist有些类似,是连续的一整块内存空间,而且对于大整数和小整数(按绝对值)采取了不同的编码,尽量对内存的使用进行了优化。

	typedef struct intset {
	    uint32_t encoding;
	    uint32_t length;
	    int8_t contents[];
	} intset;
	
	#define INTSET_ENC_INT16 (sizeof(int16_t))
	#define INTSET_ENC_INT32 (sizeof(int32_t))
	#define INTSET_ENC_INT64 (sizeof(int64_t))

各个字段含义如下:

  1. length: 表示intset中的元素个数。encoding和length两个字段构成了intset的头部(header)。
  2. contents: 是一个柔性数组(flexible array member),表示intset的header后面紧跟着数据元素。这个数组的总长度(即总字节数)等于encoding * length。柔性数组在Redis的很多数据结构的定义中都出现过(例如sds,quicklist, skiplist),用于表达一个偏移量。contents需要单独为其分配空间,这部分内存不包含在intset结构当中。
  3. encoding: 数据编码,表示intset中的每个数据元素用几个字节来存储。它有三种可能的取值:INTSET_ENC_INT16表示每个元素用2个字节存储,INTSET_ENC_INT32表示每个元素用4个字节存储,INTSET_ENC_INT64表示每个元素用8个字节存储。因此,intset中存储的整数最多只能占用64bit。

其中需要注意的是,intset可能会随着数据的添加而改变它的数据编码:

  1. 最开始,新创建的intset使用占内存最小的INTSET_ENC_INT16(两字节)作为数据编码。
  2. 每添加一个新元素,则根据元素大小决定是否对数据编码进行升级。

升级

 

如下图为一个保存了五个元素intset,且ecoding编码为INTSET_ENC_INT16(两字节,所以该编码能保存的范围为-2^{15}~2^{15}-1)

我们插入一个 32768,由于 32768 = 2^{15} 已经超出了INTSET_ENC_INT16表示范围,所以这时会引起集合的升级。值得注意的是 集合升级不仅把当前元素升级为32位,数组其他元素也会升级为32位(四个字节),如下图:

降级

整数集合不支持降级操作,一旦对数组进行了升级,编码就会一直保持升级后的状态。如上图,当我们把32768删除以后该数组还是INTSET_ENC_INT32编码。

intset与ziplist相比:

  1. ziplist可以存储任意二进制串,而intset只能存储整数。
  2. ziplist是无序的,而intset是从小到大有序的。因此,在ziplist上查找只能遍历,而在intset上可以进行二分查找,性能更高。
  3. ziplist可以对每个数据项进行不同的变长编码(每个数据项前面都有数据长度字段len),而intset只能整体使用一个统一的编码(encoding)。
原创文章 15 获赞 22 访问量 6940

猜你喜欢

转载自blog.csdn.net/qq_31387317/article/details/94461437