1. 介绍
无序并唯一的键值集合,存储顺序不按照插入顺序。支持交集、并集、差集运算。
1.1. 内部实现
哈希表或整数集合。
- 如果集合中的元素都是整数且元素个数小于
512
(默认值)个,Redis 会使用整数集合作为 Set 类型的底层数据结构; - 否则采用哈希表存储
1.1.1. 哈希表
没有用红黑树,只是桶数组 + 链表。
1.1.2. 整数集合
#整数集合 #Redis/intset
intset
整数集合其实就是一个数组,但是其会在数组的头部保存当前数组的编码类型,还有数组真实的首部地址。
当进行增加元素的命令时,会根据插入数据的大小,决定是否需要升级当前的编码,其内部共有三种编码,
int16,int32,int64
分别相当于 java 的 short,int,long 类型的数据范围。查找时采用二分查找,效率还是很快的。其判断元素地址的时候,会根据当前元素的下标,以及编码类型确定元素的真实所在地址(因为不是默认的 int 数组,所以需要自定义规则)。寻址公式:
startPtr + (sizeof(int64) * index)
得到真实地址。intset 插入数据时会保证数据是有序的,并且当编码类型改变时,会进行如下操作:
- 进行扩容,接着申请一段内存
- 然后对所有元素进行复制,复制的时候对所有元素根据逆序进行插入,主要是防止其他元素会被当前元素覆盖。
- 复制过程中,会根据新的编码类型和索引进行真实地址的求解。
1.2. 常用命令
# 往集合key中存入元素,元素存在则忽略,若key不存在则新建
SADD key member [member ...]
# 从集合key中删除元素
SREM key member [member ...]
# 获取集合key中所有元素
SMEMBERS key
# 获取集合key中的元素个数
SCARD key
# 判断member元素是否存在于集合key中
SISMEMBER key member
# 从集合key中随机选出count个元素,元素不从key中删除
SRANDMEMBER key [count]
# 从集合key中随机选出count个元素,元素从key中删除
SPOP key [count]
交并差集:
- 交集:
SINTER key [key ...]
- 并集:
SUNION key [key ...]
- 差集:
SDIFF key [key ...]
1.3. 应用场景
保证数据唯一时,如点赞,每个用户只能点赞同一个帖子一次。
可以做到:
- 获取点赞数量
- 获取点赞的所有用户 id
- 点赞和取消点赞
- 用集合运算得到共同关注的好友、公众号等。
- 抽奖活动:同一个用户只能中奖一次。