1. 集合(Set
)类型
Redis中的集合(Set
)类型类似于List
类型,Set
类型可以认为是没有排序的字符串集合。和List
类型一样,我们可以对集合类型进行元素的添加、删除或判断元素是否存在等操作。
Set
类型操作的时间复杂度为O(1)
,其最大元素数量为232-1
(40亿)。和List
类型不同的是,Set
集合中不允许出现重复的元素,如果多次添加相同元素,Set
中将仅保留该元素的一份拷贝。
和List
类型相比,Set
类型还有一个非常重要的特性,可以在服务器端完成多个集合之间的聚合计算操作,如:SUNION
、SUNIONSTORE
和SDIFFSTORE
。由于这些操作均在服务端完成,因此效率极高,而且也节省了大量的网络I/O开销。
2. 集合类型中的命令及使用
2.1 元素添加、成员判断
操作集合最基本的操作是向集合中添加元素,添加元素使用SADD
命令。还可以使用SMEMBERS
、SISMEMBER
查询集合中的成员。
2.1.1 SADD
- 添加元素
SADD key member [member ...]
将一个或多个元素member
添加到集合key
中,如果要添加的元素在集合中已存在,那么该元素将被忽略。如果集合key
不存在,那么包含元素member
的集合会被创建。
复杂度、返回值:
- 时间复杂度:
O(N)
,N
为被添加的元素数量 - 返回值:被添加到集合中的新元素的数量,不包括被忽略的元素;如果
key
不是集合类型,将返回一个错误。
使用示例
# 添加单个元素 redis> SADD blog "segmentfault.com" (integer) 1 # 添加重复元素 redis> SADD blog "segmentfault.com" (integer) 0 # 添加多个元素 redis> SADD blog "csdn.net" "itbilu.com" (integer) 2 redis> SMEMBERS blog 1) "segmentfault.com" 2) "csdn.net" 3) "itbilu.com"
2.1.2 SCARD
- 集合元素数
SCARD key
返回集合key
中元素的数量。
复杂度、返回值:
- 时间复杂度:
O(1)
- 返回值:集合中的元素数;集合不存在时,返回
0
。
使用示例
redis> SADD tool pc printer phone (integer) 3 redis> SCARD tool # 非空集合 (integer) 3 redis> DEL tool (integer) 1 redis> SCARD tool # 空集合 (integer) 0
2.1.3 SMEMBERS
- 返回集合中成员
SMEMBERS key
返回集合key
中所有的成员。如果key
不存在,会被当做空集合。
复杂度、返回值:
- 时间复杂度:
O(N)
,N
为集合的基数 - 返回值:集合中所有的成员
使用示例
# key 不存在或集合为空 redis> EXISTS not_exists_key (integer) 0 redis> SMEMBERS not_exists_key (empty list or set) # 非空集合 redis> SADD language Ruby Python Clojure (integer) 3 redis> SMEMBERS language 1) "Python" 2) "Ruby" 3) "Clojure"
2.1.4 SISMEMBER
- 判断元素是否是集合成员
SISMEMBER key member
判断元素member
是否是集合key
的成员。
复杂度、返回值:
- 时间复杂度:
O(1)
- 返回值:如果
member
是集合成员,返回1
;如果不是集合成员或集合不存在,返回0
。
使用示例
redis> SMEMBERS joe's_movies 1) "hi, lady" 2) "Fast Five" 3) "2012" redis> SISMEMBER joe's_movies "bet man" (integer) 0 redis> SISMEMBER joe's_movies "Fast Five" (integer) 1
2.2 获取集合元素、元素移除
集合类型中并不能明确返回指定的成员,但可以通过SPOP
或SRANDMEMBER
随机返回一个或多个元素成员。SREM
命令可以移除集合中指定的元素,SMOVE
可以将元素从一个元素移至另一个元素。
2.2.1 SPOP
- 随机返回并移除一个元素
SPOP key
随机移除并返回集合key
中的一个元素。
复杂度、返回值:
- 时间复杂度:
O(1)
- 返回值:被移除的元素;如果
key
不存在或集合为空,则返回nil
使用示例
redis> SMEMBERS db 1) "MySQL" 2) "MongoDB" 3) "Redis" redis> SPOP db "Redis" redis> SMEMBERS db 1) "MySQL" 2) "MongoDB" redis> SPOP db "MySQL" redis> SMEMBERS db 1) "MongoDB"
2.2.2 SRANDMEMBER
- 随机返回一个或多个元素
SRANDMEMBER key [count]
如果可选参数count
未提供,则随机集合key
中的一个元素。count
元素提供时,则按以下规则返回:
count
小于集合元素总数,则随机返回数量为count
的元素。如果大于总数,则返回全部元素。- 如果
count
为负数,则返回一个数量为其绝对值的的元素。
复杂度、返回值:
- 时间复杂度:未提供
count
时O(1)
;提供是为O(N)
,N
为返回数组的元素个数 - 返回值:一个元素或数量为
count
的数组;集合为空则返回nil
或空数组。
使用示例
# 添加元素 redis> SADD fruit apple banana cherry (integer) 3 # 只给定 key 参数,返回一个随机元素 redis> SRANDMEMBER fruit "cherry" redis> SRANDMEMBER fruit "apple" # 给定 3 为 count 参数,返回 3 个随机元素 # 每个随机元素都不相同 redis> SRANDMEMBER fruit 3 1) "apple" 2) "banana" 3) "cherry" # 给定 -3 为 count 参数,返回 3 个随机元素 # 元素可能会重复出现多次 redis> SRANDMEMBER fruit -3 1) "banana" 2) "cherry" 3) "apple" redis> SRANDMEMBER fruit -3 1) "apple" 2) "apple" 3) "cherry" # 如果 count 是整数,且大于等于集合基数,那么返回整个集合 redis> SRANDMEMBER fruit 10 1) "apple" 2) "banana" 3) "cherry" # 如果 count 是负数,且 count 的绝对值大于集合的基数 # 那么返回的数组的长度为 count 的绝对值 redis> SRANDMEMBER fruit -10 1) "banana" 2) "apple" 3) "banana" 4) "cherry" 5) "apple" 6) "apple" 7) "cherry" 8) "apple" 9) "apple" 10) "banana" # SRANDMEMBER 并不会修改集合内容 redis> SMEMBERS fruit 1) "apple" 2) "cherry" 3) "banana" # 集合为空时返回 nil 或者空数组 redis> SRANDMEMBER not-exists (nil) redis> SRANDMEMBER not-eixsts 10 (empty list or set)
2.2.3 SREM
- 移除指定的元素
SREM key member [member ...]
移除集合key
中指定的一个或多个元素member
,如果member
不存在会被忽略。
复杂度、返回值:
- 时间复杂度:
O(N)
,N
为指定的member
数量 - 返回值:被移除的元素数量;如果
key
不是集合类型,会返回一个错误。
使用示例
# 测试数据 redis> SMEMBERS languages 1) "c" 2) "lisp" 3) "python" 4) "ruby" # 移除单个元素 redis> SREM languages ruby (integer) 1 # 移除不存在元素 redis> SREM languages non-exists-language (integer) 0 # 移除多个元素 redis> SREM languages lisp python c (integer) 3 redis> SMEMBERS languages (empty list or set)
2.2.4 SMOVE
- 将元素从集合移至另一个集合
SMOVE source destination member
将元素member
从集合source
移动至集合destination
。
如果元素在集合source
中不存在,则不进行任何操作;如果destination
中已存在该元素,则仅从source
中删除该元素。
复杂度、返回值:
- 时间复杂度:
O(1)
- 返回值:元素移动成功返回
1
;其它情况返回0
使用示例
redis> SMEMBERS songs 1) "Billie Jean" 2) "Believe Me" redis> SMEMBERS my_songs (empty list or set) redis> SMOVE songs my_songs "Believe Me" (integer) 1 redis> SMEMBERS songs 1) "Billie Jean" redis> SMEMBERS my_songs 1) "Believe Me"
2.3 集合间的操作
集合类型中还提供了集合间操作的命令,这些命令在服务器端操作,执行效率非常高。集间的操作有:差集、交集、并集,命令有返回指定的集合元素,或将操作结果存储至一个新集合。
2.3.1 SDIFF
- 返回一或多个集合的差集
SDIFF key [key ...]
返回指定的一个或多个集合的差集。
复杂度、返回值:
- 时间复杂度:
O(N)
,N
为指定集合的成员数量之和。 - 返回值:差集成员列表。
使用示例
redis> SMEMBERS peter's_movies 1) "bet man" 2) "start war" 3) "2012" redis> SMEMBERS joe's_movies 1) "hi, lady" 2) "Fast Five" 3) "2012" redis> SDIFF peter's_movies joe's_movies 1) "bet man" 2) "start war"
2.3.2 SDIFFSTORE
- 将一或多个集合的差集保存至另一集合
SDIFFSTORE destination key [key ...]
该命令与SDIFF
类型,但它不会直接返回,而是将差集存储到另一集合destination
中。如果destination
已存在,则将其覆盖。
复杂度、返回值:
- 时间复杂度:
O(N)
,N
为指定集合的成员数量之和。 - 返回值:结果交集成员数量。
使用示例
redis> SMEMBERS joe's_movies 1) "hi, lady" 2) "Fast Five" 3) "2012" redis> SMEMBERS peter's_movies 1) "bet man" 2) "start war" 3) "2012" redis> SDIFFSTORE joe_diff_peter joe's_movies peter's_movies (integer) 2 redis> SMEMBERS joe_diff_peter 1) "hi, lady"
2.3.3 SINTER
- 将一或多个集合的交集保存至另一集合
SINTER key [key ...]
返回一个或多个指定集合的交集。如果指定的key
不存在,会被视为空集合,返回的结果集也为空。
复杂度、返回值:
- 时间复杂度:
O(N*M)
,N
为指定集合中基数最小的集合,M
为指定集合的数量。 - 返回值:交集成员列表。
使用示例
redis> SMEMBERS group_1 1) "LI LEI" 2) "TOM" 3) "JACK" redis> SMEMBERS group_2 1) "HAN MEIMEI" 2) "JACK" redis> SINTER group_1 group_2 1) "JACK"
2.3.4 SINTERSTORE
- 将一或多个集合的交集存储到新集合
SINTERSTORE destination key [key ...]
该命令类似于SINTER
,但它不会返回成员列表,而是将结果集存储至一个新的集合destination
中。
复杂度、返回值:
- 时间复杂度:
O(N*M)
,N
为指定集合中基数最小的集合,M
为指定集合的数量。 - 返回值:结果集中的成员数量。
使用示例
redis> SMEMBERS songs 1) "good bye joe" 2) "hello,peter" redis> SMEMBERS my_songs 1) "good bye joe" 2) "falling" redis> SINTERSTORE song_interset songs my_songs (integer) 1 redis> SMEMBERS song_interset 1) "good bye joe"
2.3.5 SUNION
- 返回集合的并集
SUNION key [key ...]
返回一个或多个集合的并集;如果key
不存在,会被视为空集合。
复杂度、返回值:
- 时间复杂度:
O(N)
,N
为所有集合成员之和 - 返回值:并集成员列表。
使用示例
redis> SMEMBERS songs 1) "Billie Jean" redis> SMEMBERS my_songs 1) "Believe Me" redis> SUNION songs my_songs 1) "Billie Jean" 2) "Believe Me"
2.3.6 SUNIONSTORE
- 将集合的并集插入新集合
SUNIONSTORE destination key [key ...]
此命令类似于SUNION
,但它不会直接返回集合的交集,而是将结果插入一个新的集合destination
。如果destination
已存在,则将其覆盖。
复杂度、返回值:
- 时间复杂度:
O(N)
,N
为所有集合成员之和 - 返回值:并集元素数量。
使用示例
redis> SMEMBERS NoSQL 1) "MongoDB" 2) "Redis" redis> SMEMBERS SQL 1) "sqlite" 2) "MySQL" redis> SUNIONSTORE db NoSQL SQL (integer) 4 redis> SMEMBERS db 1) "MySQL" 2) "sqlite" 3) "MongoDB" 4) "Redis"