小白都能看懂的Redis数据类型-集合详解

65 阅读3分钟

持续创作,加速成长!这是我参与「掘金日新计划 · 10 月更文挑战」的第6天,点击查看活动详情

集合和list类似但是又不尽相同,集合set内的元素是无序且不能重复的,所以不能根据下标获取元素。
一个集合最多存储2³²-1个元素。且set比list多了集合取交集并集差集等操作。

先看看集合支持的命令吧

1 命令

1.1 集合内操作

1.1.1 添加元素

sadd key value命令可以向集合中添加元素。

127.0.0.1:6379> sadd name a b c d
(integer) 4
127.0.0.1:6379> sadd name a c
(integer) 0

值得注意的是,当添加的元素已经存在的时候,sadd命令会返回0

1.1.2 删除元素

srem key member可以移除集合内的指定元素,返回移除成功的个数

127.0.0.1:6379> srem name a
(integer) 1

1.1.3 计算元素个数

scard key可以返回key内集合的元素个数,也就是集合的大小

127.0.0.1:6379> scard name
(integer) 3

这个命令并不会轮询整个list,而是读取了redis的内部变量,所以时间复杂度是O(1)。

1.1.4 判断元素是否在集合中

sismember key member当返回1的时候,是当前member存在集合中,返回0则是不存在。

127.0.0.1:6379> sismember name a
(integer) 0
127.0.0.1:6379> sismember name b
(integer) 1

对于这个例子,由于上边我们把a删除了,所以当查看a存在不存在的时候返回0。

1.1.5 随机返回指定集合内的指定个数的元素

srandmember key count可以随机返回key内count个元素

127.0.0.1:6379> srandmember name 2
1) "c"
2) "d"

count也可以不写,默认就是1

1.1.6 从集合中随机弹出元素

spop key可以从集合中弹出元素

127.0.0.1:6379> spop name
"d"

在3.2版本之后,spop命令也支持设置个数了,也就是命令可写为spop key count
spop和srandmember的区别是

  • spop弹出元素,剩下的元素会减一,减去弹出的元素
  • srandmember只是返回值,不会改变原集合

1.1.7 获取所有元素

获取所有的命令是smembers key

127.0.0.1:6379> smembers name
1) "c"
2) "b"

经过我们上边一系列的操作,name内的元素就剩b和c了。

1.2 集合间操作

我们创建两个集合

127.0.0.1:6379> sadd name1 a b c d
(integer) 4
127.0.0.1:6379> sadd name2 a e f d
(integer) 4

1.2.1 取多个集合的交集

取交集的命令是sinter key ...,它可以传入一个或者多个key

127.0.0.1:6379> sinter name1 name2
1) "a"
2) "d"

当只传入一个集合的时候,会返回这个集合的所有值

127.0.0.1:6379> sinter name1
1) "c"
2) "b"
3) "a"
4) "d"

1.2.2 取多个集合的并集

sunion key ...可以求多个集合的并集

127.0.0.1:6379> sunion name1 name2
1) "a"
2) "d"
3) "c"
4) "e"
5) "f"
6) "b"

1.2.3 取多个集合的差集

sdiff key ...可以求多个集合的差集

127.0.0.1:6379> sdiff name1 name2
1) "c"
2) "b"

1.2.4 保存交集,差集并集的结果

在我们求到集合的交集,并集,差集的时候,可以将他们保存到新的key里边 命令对应的是:
sinterstore newkey key ...
sunionstore newkey key ...
sdiffstore newkey key ...
这三个基本就相同了,都是求值然后保存到新的key里边,我们举一个例子看看

127.0.0.1:6379> sinterstore name3 name1 name2
(integer) 2
127.0.0.1:6379> smembers name3
1) "a"
2) "d"

2 内部编码

集合的内部编码有两种 intsethashtable

2.1 intset

使用这个内部编码有两个条件

  1. 元素都是整数
  2. 元素个数小于配置的set-max-intset-entries,默认是512

intset会占用更小的内存

2.2 hashtable

当集合内的元素不满足上边的两个条件的时候,则会使用hashtable作为集合的内部实现

3 使用场景

集合比较典型的使用场景是标签

比如用一个集合保存用户的爱好,求出两个用户的爱好交集就是共同爱好了。

又因为集合内元素不重复,可以使用集合统计网站的访问用户量。可以看出当天有多少活跃用户