集合(REDIS_SET)

第一个添加到集合的元素, 决定了创建集合时所使用的编码:

  • 如果第一个元素可以表示为 long long 类型值(也即是,它是一个整数, 接口isObjectRepresentableAsLongLong), 那么集合的初始编码为 REDIS_ENCODING_INTSET 。
  • 否则,集合的初始编码为 REDIS_ENCODING_HT

如果一个集合使用 REDIS_ENCODING_INTSET 编码, 那么当以下任何一个条件被满足时, 这个集合会被转换成 REDIS_ENCODING_HT 编码:

  • intset 保存的整数值个数超过 server.set_max_intset_entries (默认值为 512 )。
  • 试图往集合里添加一个新元素,并且这个元素不能被表示为 long long 类型(也即是,它不是一个整数)。

1.  整数集合(REDIS_ENCODING_INTSET)的内存结构


2.  哈希集合的内存结构: 将字典的key作为存储数据的value;而将value置为NULL.



1. 集合的交集算法:

示例:
redis 127.0.0.1:6379> smembers myset2
1) "three"
2) "two"
redis 127.0.0.1:6379> smembers myset3
1) "two"
2) "one"
redis 127.0.0.1:6379> sinter myset2 myset3
1) "two"

 1).  将所有需要计算交集的集合放到到一个集合数组中;
 2).  对数组进行排序,排序的数序是由各个集合的基数(即集合中成员个数)从小到大排序的,这样排序是因为后续查找比较过程中,从小的集合中找到相同的元素的概率比较小,如果找不到就中断这个元素的查找;并且最小集合的元素较少,外面的循环的次数也最小,这样效率比较高;
 3) 双重循环进行比较查找: 从第一个集合中(最小元素个数)取各个元素和其他的集合中元素进行比较,如果在其他集合中都存在则记录下来。

2. 集合的并集算法:
示例:
redis 127.0.0.1:6379> smembers myset2
1) "three"
2) "two"
redis 127.0.0.1:6379> smembers myset3
1) "two" 
2) "one"
redis 127.0.0.1:6379> sunion myset2 myset3
1) "three"
2) "one"
3) "two"

   1).  将所有需要计算交集的集合放到到一个集合数组中;
   2).  双重遍历所有的集合,将元素添加的新的集合中,重复元素会添加失败;


 3. 集合的差集算法:
示例:
redis 127.0.0.1:6379> smembers myset2
1) "three"
2) "two"
redis 127.0.0.1:6379> smembers myset3
1) "two"
2) "one"
redis 127.0.0.1:6379> sdiff myset2 myset3
1) "three"

   1).  将所有需要计算交集的集合放到到一个集合数组中;
   2). 差集的计算有两种算法:
      a): 将数组中从sets[1]开始按基数从大到小排序(sets[0]位置不动), 这样可以在后续计算中尽快找到重复元素, 遍历sets[0]中的各个元素,如果某个元素在其他的集合中不存在, 则插入的新的差集集合(目的集合)中;算法的复杂度是O(N*M): N是sets[0]中元素的个数, M是集合的个数。
 
      b): 不对sets[]进行排序,将sets[0]中的所有元素都放到新的差集集合(目的集合)中;然后遍历所有的剩余的集合(从sets[1]开始)的元素,如果在目的集合中存在,则从目的集合中删除该元素。算法的复杂度是O(N): N是所有集合元素的个数。

    两种算法的选择是由两种算法的复杂度来比较选择哪种算法,因为第一种算法中只要找到一个集合中有不存在的查找的元素内循环就退出,因此对第一种算法的优先级进行提高(algo_one_work /= 2;),即对第一种进行除2提高。





發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章