12.set集合
-
Redis set (集合) 数据类型由键值对组成,这些键值对遵循无序排列、唯一的规则,集合中的每一个成员(也就是元素)都是字符串类型,并且不可重复。Redis set 是通过哈希映射表实现的,所以它的添加、删除、查找操作的时间复杂度为 O(1)。集合中最多可容纳 2^32 - 1 个成员(40 多亿个)。单值多value。
-
set 使用以下方式向集合中添加一个成员,语法格式如下:
127.0.0.1:6379> SADD key member [member ...]
#key:指定一个键
#member:集合中要存储的成员。
-
和其他数据类型一样,当集合中最后一个成员被删除时,存储成员所用的数据结构也会被自动删除。集合有一个非常重要的特性就是“自动去重”,这使得它可以适用于许多场景,比如过滤掉已领券的用户的 id,保证该用户不会被第二次领券。
-
Redis set 采用了两种方式相结合的底层存储结构,分别是intset(整型数组)与 hash table(哈希表),当 set 存储的数据满足以下要求时,使用 intset 结构:
- 集合内保存的所有成员都是整数值;
- 集合内保存的成员数量不超过 512 个。
-
当不满足上述要求时,则使用 hash table 结构。Redis 中 intset 的结构体定义如下:
typedf struct inset{
uint32_t encoding;//指定编码方式,默认为INSET_ENC_INT16
uint32_t length;//集合内成员的总个数
int8_t contents[];//实际存储成员的数组,并且数组中的数值从小到大依次排列
}inset;
- encoding:用来指定编码格式,共有三种,分别是 INTSET_ENC_INT16、INSET_ENC_INT32 和 INSET_ENC_INT64,它们对应不同的数值范围。Redis 为了尽可能地节省内存,它会根据插入数据的大小来选择不同的编码格式。
- length:集合内成员的数量,记录 contents 数组中共有多少个成员。
- contents:存储成员的数组,数组中的成员从小到大依次排列,且不允许重复。
- intset 结构示意图如下所示: set 的哈希表原理与hash哈希散列相似。
12.1 命令汇总
命令 | 说明 |
---|---|
SADD key member1 [member2] | 向集合中添加一个或者多个元素,并且自动去重。 |
SCARD key | 返回集合中元素的个数。 |
SDIFF key1 [key2] | 求两个或多个集合的差集。 |
SDIFFSTORE destination key1 [key2] | 求两个集合或多个集合的差集,并将结果保存到指定的集合中。 |
SINTER key1 [key2] | 求两个或多个集合的交集。 |
SINTERSTORE destination key1 [key2] | 求两个或多个集合的交集,并将结果保存到指定的集合中。 |
SISMEMBER key member | s is member查看指定元素是否存在于集合中,存在为1、不存在为0。 |
SMEMBERS key | 查看集合中所有元素。 |
SMOVE source destination member | 将集合中的元素移动到指定的集合中。 |
SPOP key [count] | 弹出指定数量的元素。 |
SRANDMEMBER key [count] | 随机从集合中返回指定数量的元素,默认返回 1个。 |
SREM key member1 [member2] | 删除一个或者多个元素,若元素不存在则自动忽略。 |
SUNION key1 [key2] | 求两个或者多个集合的并集。 |
SUNIONSTORE destination key1 [key2] | 求两个或者多个集合的并集,并将结果保存到指定的集合中。 |
SSCAN key cursor [match pattern] [count count] | 该命令用来迭代的集合中的元素。 |
12.2 SADD、SMEMBERS命令
-
SADD 命令将一个或多个 member 元素加入到集合 key 当中,已经存在于集合的 member 元素将被忽略。若 key 不存在,则自动创建一个包含 member 元素的集合。当 key 不是集合类型时,返回一个错误。命令可用版本:>= 1.0.0
-
SMEMBERS 命令返回集合 key 中的所有成员,不存在的 key 被视为空集合。命令可用版本:>= 1.0.0
-
命令的基本语法如下:
#SADD 命令的基本语法如下:
SADD key member [member ...]
#SMEMBERS 命令的基本语法如下:
SMEMBERS key
-
SADD 命令的返回值:被添加到集合中的新元素的数量,不包括被忽略的元素。
-
SMEMBERS 命令的返回值:集合中的所有成员。不用写从零到负一就表示全部,但是不能重读
-
命令演示:
#创建key为course的hash散列
local:0>lpush course java php
"2"
local:0>lrange course 0 8
1) "php"
2) "java"
#由于key不是集合类型,所以添加失败
local:0>sadd course c++ c# .net
"WRONGTYPE Operation against a key holding the wrong kind of value"
#删除hash表key
local:0>del course
"1"
#重新创建key为course的set集合添加元素,这次成功
local:0>sadd course c++ c# .net java php
"5"
#添加重复元素失败
local:0>sadd course php
"0"
#查看所有元素
local:0>smembers course
1) ".net"
2) "java"
3) "c++"
4) "c#"
5) "php"
12.3 SCARD命令
- SCARD 命令返回集合 key 的基数(集合中元素的数量)。命令可用版本:>= 1.0.0。SCARD 命令的基本语法如下:
SCARD key
- SCARD 命令的返回值集合的基数,即元素的个数。若 key 不存在时,则返回 0。命令演示:
#向集合添加元素
local:0>sadd course c++ c# .net java php
"5"
#集合自动去重,添加重复元素会失败
local:0>sadd course php
"0"
#查看所有元素
local:0>smembers course
1) ".net"
2) "java"
3) "c++"
4) "c#"
5) "php"
#查看集合的基数,即元素的个数
local:0>scard course
"5"
12.4 SRANDMEMBER命令
-
SRANDMEMBER 命令,该命令执行时,如果只提供了 key 参数,那么返回集合中的一个随机元素。 命令可用版本:>= 1.0.0
-
从 Redis 2.6 版本开始, SRANDMEMBER 命令允许接受可选参数 count,该参数描述如下:
- 如果 count 为正数,且小于集合基数,那么命令返回一个包含 count 个元素的数组,数组中的元素各不相同。
- 如果 count 大于等于集合基数,那么返回整个集合。
- 如果 count 为负数,那么返回数组中的元素可能会重复出现多次,而数组的长度为 count 的绝对值。
-
Redis SRANDMEMBER 命令的基本语法如下:
SRANDMEMBER key [count]
- SRANDMEMBER 命令的返回值:只提供 key 参数时,返回一个元素;如果集合为空,返回 null 。如果提供了 count 参数,那么返回一个数组,此时若集合为空,则返回空数组。命令演示
set集合无序不重复,该命令适用于抽奖环节
#向集合添加元素
local:0>sadd course c++ c# .net java php
"5"
#查看所有元素
local:0>smembers course
1) ".net"
2) "java"
3) "c++"
4) "c#"
5) "php"
#返回两个元素
local:0>srandmember course 2
1) "php"
2) "java"
local:0>srandmember course 9
1) "c#"
2) ".net"
3) "java"
4) "c++"
5) "php"
local:0>srandmember course -2
1) "java"
2) "php"
local:0>srandmember course -6
1) "c#"
2) "java"
3) "java"
4) ".net"
5) "php"
6) ".net"
12.5 SDIFF、SDIFFSTORE命令
-
SDIFF 命令返回第一个集合与其他集合之间的差集,也可以认为是第一个集合中独有的元素。对于不存在的集合 key 将被视为空集。命令可用版本:>= 1.0.0
-
SDIFFSTORE 命令与 SDIFF 命令作用类似,但前者是将结果保存到 destination 集合,而不是简单地返回结果集。如果 destination 集合已经存在,则将其覆盖。destination 可以是 key 本身。命令可用版本:>= 1.0.0
-
命令的基本语法如下:
#SDIFF 命令的基本语法如下:
SDIFF key [key ...]
#SDIFFSTORE 命令的基本语法如下:
SDIFFSTORE destination key [key ...]
-
SDIFF 命令的返回值:包含了差集成员的列表。
-
SDIFFSTORE 命令的返回值结果集 destination 中的元素数量。
-
命令演示:
#向集合添加元素
local:0>sadd course c++ c# .net java php
"5"
local:0>sadd lesson java php c# lua sql
"5"
#查看所有元素
local:0>smembers course
1) "c#"
2) "php"
3) "java"
4) "c++"
5) ".net"
local:0>smembers lesson
1) "c#"
2) "php"
3) "java"
4) "lua"
5) "sql"
#求course的差集
local:0>sdiff course lesson
1) ".net"
2) "c++"
#将差集成员保存到myresul目标集合中
local:0>sdiffstore myresult course lesson
"2"
local:0>smembers myresult
1) ".net"
2) "c++"
12.6 SINTER、SINTERSTORE命令
-
SINTER 命令返回一个集合的全部成员,该集合是所有给定集合的交集。对于不存在的 key 被视为空集。如果给定的集合中存在一个空集时,结果也为空集(根据集合运算定律)。命令可用版本:>= 1.0.0
-
SINTERSTORE 命令与 SINTER 命令类似,但前者会将结果保存到 destination 集合,而不是简单地返回结果集。如果 destination 集合已经存在,则将其覆盖。destination 可以是 key 本身。命令可用版本:>= 1.0.0。适用场景:网站中的共同关注
-
命令的基本语法如下:
#SINTER 命令的基本语法如下:
SINTER key [key ...]
#SINTERSTORE 命令的基本语法如下:
SINTERSTORE destination key [key ...]
-
SINTER 命令的返回值交集成员的列表。
-
SINTERSTORE 命令的返回值:结果集中的成员数量。
-
命令演示
#向集合添加元素
local:0>sadd course c++ c# .net java php
"5"
local:0>sadd lesson java php c# lua sql
"5"
#求两个集合的交集
local:0>sinter course lesson
1) "php"
2) "c#"
3) "java"
#求与空集合的交集
local:0>sinter course lesson lessons
#求两个集合的交集,并保存至另外一个集合
local:0>sinterstore myresults course lesson
"3"
local:0>smembers myresults
1) "c#"
2) "php"
3) "java"
12.7 SUNION、SUNIONSTORE命令
-
SUNION 命令返回一个集合的全部成员,该集合是所有给定集合的并集。命令可用版本:>= 1.0.0
-
SUNIONSTORE 命令类似于 SUNION 命令,但它将结果保存到 destination 集合,而不是简单地返回结果集。如果 destination 已经存在,则将其覆盖。destination 可以是 key 本身。命令可用版本:>= 1.0.0
-
命令的基本语法如下:
#SUNION 命令的基本语法如下:
SUNION key [key ...]
#SUNIONSTORE 命令的基本语法如下:
SUNIONSTORE destination key [key ...]
-
SUNION 命令的返回值:并集成员的列表。
-
SUNIONSTORE 命令的返回值:结果集中的元素数量。
-
命令演示:
#向集合添加元素
local:0>sadd course c++ c# .net java php
"5"
local:0>sadd lesson java php c# lua sql
"5"
#求并集
local:0>sunion course lesson
1) "c#"
2) "php"
3) "java"
4) "lua"
5) "c++"
6) "sql"
7) ".net"
#将结果存储在一个目标集合myresult
local:0>del myresult
"1"
local:0>sunionstore myresult course lesson
"7"
local:0>smembers myresult
1) "c#"
2) "php"
3) "java"
4) "lua"
5) "c++"
6) "sql"
7) ".net"
12.8 SMOVE命令
-
SMOVE 命令将 member 成员从一个集合(source)移动至另一个集合(destination)。如果 source 集合不存在,或者不包含指定的 member 元素,则 SMOVE 命令不执行任何操作,仅返回 0。否则, member 元素从 source 集合中被移除,并添加到 destination 集合中去。
-
当 destination 集合已经包含 member 元素时, SMOVE 命令只是简单地将 source 集合中的 member 元素删除。当 source 或 destination 不是集合类型时,返回一个错误信息。命令可用版本:>= 1.0.0
-
SMOVE 命令的基本语法如下:
SMOVE source destination member
- SMOVE 命令的返回值:如果 member 元素被成功移除,返回 1。如果 member 元素不是 source 集合的成员,那么将返回 0 。命令演示
remote:0>type course
"list"
#当 source 或 destination 不是集合类型时,返回一个错误信息
remote:0>smove course dest c#
"WRONGTYPE Operation against a key holding the wrong kind of value"
remote:0>del course
"1"
remote:0>sadd course c++ c# .net java php
"5"
#自动创建dest集合
remote:0>smove course dest java
"1"
#查看移动后的目的集合
remote:0>smembers dest
1) "java"
#查看移动后的源集合
remote:0>smembers course
1) "c++"
2) ".net"
3) "c#"
4) "php"
12.9 SPOP命令
- SPOP 命令移除并返回集合中的一个随机元素。命令可用版本:>= 1.0.0。 SPOP 命令的基本语法如下:
SPOP key [count]
#count 表示随机移除成员的数量。该参数在 Redis 3.2 版本才被使用。
- SPOP 命令的返回值:被移除的随机元素。当 key 不存在或 key 是空集时,返回 null。命令演示
#添加一个集合成员
remote:0>sadd course c++ c# .net java php
"5"
#随机删除一个成员
remote:0>spop course
"c++"
remote:0>spop course 2
1) "java"
2) ".net"
#查看成员,为空列表
remote:0>smembers mysult
# key 不存在或 key 是空集时,返回 null。
remote:0>spop mysult
null
12.10 SREM命令
-
SREM 命令移除集合 key 中的一个或多个 member 元素,不存在的 member 元素会被忽略。当 key 不是集合类型,返回一个错误。在 Redis 2.4 版本以前,SREM 只接受单个 member 值。命令可用版本:>= 1.0.0
-
SREM 命令的基本语法如下:
SREM key member [member ...]
- SREM 命令的返回值:被成功移除的元素的数量,不包括被忽略的元素。命令演示
remote:0>sadd course c++ c# .net java php
"5"
#查看所有元素
remote:0>smembers course
1) "c++"
2) "c#"
3) "php"
4) "java"
5) ".net"
#删除2个成员
remote:0>srem course c# java
"2"
#查看剩余成员
remote:0>smembers course
1) "c++"
2) "php"
3) ".net"
#迭代集合中元素
remote:0>sscan course 0
1) "0"
2) 1) "c++"
2) "php"
3) ".net"