一、集合(Set)简介
Redis的集合建和列表键相似,允许将任意多个元素存储到集合中,但集合与列表有两个区别:
- 列表可以存储重复元素,而集合只会存储非重复元素,如果将一个重复的元素添加到集合中,将被忽略;
- 列表以有序方式存储元素,而集合中的元素是无序存放的。
这两个区别带来的差异主要体现在命令的复杂度,在执行像LINSERT和LREM这种针对单个元素的命令时,程序有时候不得不遍历整个列表以确定指定的元素是否存在,因此这些命令的复杂度都是O(N);而对于集合来说,所有针对单个元素的命令都不需要遍历整个集合,所以复杂度为(O1)。因为Redis中列表list底层使用quicklist实现,集合set底层使用intset和哈希表实现。
当我们需要存储多个元素时,如果可以以无序方式存储,并且需要不重复,就可以使用集合来存储这些元素,从而有效利用集合操作的效率优势。
二、集合Set常用命令
- 添加元素到集合
通过使用SADD命令,可以将一个或多个元素添加到集合中;
语法格式:SADD key element1 element2 …,如
# 向集合fruit中添加三个元素apple、orange、banana
SADD fruit 'apple' 'orange' 'banana'
当指定集合不存在时,会先创建集合,再添加元素;添加时遇到已存在的数据时,会将其忽略。
- 从集合中移除数据
和列表的LREM命令神似,集合的移除命令是SREM,可用于从集合中移除一个或多个数据;
语法格式:SREM key element1 element2 …,如
# 移除集合fruit中的orange和banana
SREM fruit 'orange' 'banana'
如果用户给定的元素并不存在于集合当中,那么SREM命令将忽略不存在的元素,只移除那些确实存在的元素。
- 随机从集合中移除指定数量的元素
SPOP命令用于从集合中随机的移除指定数量的元素
语法格式:SPOP key [count],[count]表示数量可选,当不指定时只移除一个元素,如
# 随机移除fruit集合中的一个元素
SPOP fruit
# 随机移除fruit集合中的3个元素
SPOP fruit 3
SPOP命令会返回被移除的元素作为返回值
- 将元素从一个集合移动到另一个集合
SMOVE命令用于将一个指定的元素从源集合移动到另一个集合
语法格式:SMOVE source target element,如
# 将fruit集合中的apple移动到bukets集合
SMOVE fruit bukets 'apple'
如果源集合中不存在想要移动的元素,那么SMOVE将放弃执行移动操作,并返回0表示移动操作执行失败
- 获取集合中的所有元素
通过使用SMEMBERS命令,可以获取集合包含的所有元素(member,成员的意思)
语法格式:SMEMBERS key ,如
# 获取fruit集合中的所有元素
SMEMBERS fruit
- 随机获取集合中的元素
通过使用SRANDMEMBER命令,可以获取指定集合中的随机元素,并且可以指定获取数量(RAND是random的简写,随机的意思)
语法格式:SRANDMEMEBR key [count],[count]表示数量可选,不指定时获取一个,如
#获取集合fruit中的随机一个元素
SRANDMEMBER fruit
#获取fruit集合中随机两个元素
SRANDMEMBER fruit 2
count也可以是负值,当其为负数时,就取绝对值,如-3 表明随机获得3个元素
SRANDMEMBER命令与SPOP命令的区别在于SOPO命令会移除随机选中的元素,而SRANDMEMEBR命令则不会
- 获取集合中元素的数量
获取集合中元素数量的命令是SCARD命令
语法格式:SCARD key ,如
#获取fruit集合中元素的数量
SCARD fruit
- 判断集合中是否包含给定元素
通过使用SISMEMBER命令,可以判断集合中是否包含给定元素
语法格式:SISMEMBERS key element,如
# 判断fruit集合中是否含有strawberry
SISMEMBERS fruit 'strawberry'
SISMEMBERS命令返回1表示给定的元素存在于集合中,而放回0表示不存在
- 获取多个集合中相同的元素
SINTER命令可以计算出用户给定的所有集合的交集,然后返回这个交集中的所有元素
语法格式:SINTER key1 key2 …,如
# 获取fruit和bukets中相同的元素
SINTER fruit bukets
除此之外,还有一个SINTERSTORE命令,这个命令key把给定集合的交集计算结果存储到指定的key当中,语法格式为SINTERSTORE destination_key key1 key2 …,如果给定的destination_key已经存在,那么SINTERSTORE命令在执行存储操作之前会先删除已有的键,在SINTERSTORE命令执行完后将返回被存储的交集元素的个数作为返回值。
- 获取多个集合的所有元素
SUNION命令可以计算出给定的所有集合的并集,也就是说可以将给定集合的元素进行合并返回,同时会去重
语法格式:SUNION key1 key2 …,如
# 获取fruit和bukets中的所有元素
SUNION fruit bukets
与SINTERSTORE命令类似,SUNIONSTORE命令可将并集的计算结果存储到指定的key中。
- 获取指定多个集合中所有不相同的元素
SDIFF命令用于获得多个集合之间的差集,也就是说如果一个集合中有元素 a、b、c,另一个集合中有元素c、d,那么它们的差集就是a、b
语法格式:SDIFF key1 key2 …
与SINTERSTORE和SUNIONSTORE相似,SDIFF对应的有SDIFFSTORE命令
对集合执行交集、并集、差集计算时,会耗费大量资源,且当涉及的元素数量非常大时,Redis服务器在计算时可能会被阻塞,这时可以考虑使用Redis的复制功能,通过从服务器来执行集合计算任务,从而确保主服务器可以继续处理其他客户端的命令请求。