集合和散列都可以存储多个字符串,它们之间的不同在于,列表可以存储多个相同的字符串,而集合则通过使用散列表来保证自己存储的每个字符串都是各不相同的。
集合是无序的方式存储各不相同的元素
命令
命令 | 描述 | 返回值和备注 |
---|---|---|
sadd | sadd k-name item[item…]–将一个或多个集合中不存在的元素加入到集合中 | 成功添加的元素,不包括被忽略的元素 |
srem | srem k-name item[item…]–从集合中移除元素,不存在的成员元素会被忽略 | 返回被移除的元素数量 |
Sismember | SISMEMBER k-name item --判断元素是否存在于集合中 | 如果成员元素是集合的成员,返回 1 。 如果成员元素不是集合的成员,或 key 不存在,返回 0 |
Scard | SCARD k-name–求集合中包含元素的数量 | 当集合 key 不存在时,返回 0 |
Smembers | Smembers k-name --返回集合中所有成员 | 如果集合太大可能会阻塞服务器,不推荐使用,推荐使用sscan |
Srandmember | Srandmember k-name [count]–从集合中随机返回一个或者多个元素 | |
spop | spop k-name --随机移除集合中的一个元素 | 返回被移除的元素,当集合不存在或是空集时,返回 nil |
smove | smove source-key dest-key item–将指定成员 member 元素从 source 集合移动到 destination 集合 | 如果操作成功返回1,失败返回0 |
操作元素
sadd:添加元素
作用
- 将一个或多个成员元素加入到集合中,已经存在于集合的成员元素将被忽略。
- 当集合 key 不存在,则创建一个只包含添加的元素作成员的集合。
- 当集合 key 不是集合类型时,返回一个错误。
语法
sadd key value1 ... valueN
返回值
- 被添加到集合中的新元素的数量,不包括被忽略的元素。
实例
redis 127.0.0.1:6379> SADD myset "hello"
(integer) 1
redis 127.0.0.1:6379> SADD myset "foo"
(integer) 1
redis 127.0.0.1:6379> SADD myset "hello"
(integer) 0
redis 127.0.0.1:6379> SMEMBERS myset
1) "hello"
2) "foo"
Srem:移除元素
作用
- Redis Srem 命令用于移除集合中的一个或多个成员元素,不存在的成员元素会被忽略。
- 当 key 不是集合类型,返回一个错误。
- 在 Redis 2.4 版本以前, SREM 只接受单个成员值。
语法
srem key meme1 ... memeN
时间复杂度
O(N), N 为给定 member 元素的数量。
返回值
被成功移除的元素的数量,不包括被忽略的元素。
实例
# 测试数据
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)
spop:随机删除n个元素
作用
- 用于移除集合中的指定 key 的一个或多个随机元素,移除后会返回移除的元素。
该命令类似 Srandmember 命令,但 SPOP 将随机元素从集合中移除并返回,而 Srandmember 则仅仅返回随机元素,而不对集合进行任何改动。
语法
SPOP key [count]
count 参数在 3.2+ 版本可用。
返回值
- 被移除的随机元素。
- 当集合不存在或是空集时,返回 nil 。
实例
redis> SADD myset "one"
(integer) 1
redis> SADD myset "two"
(integer) 1
redis> SADD myset "three"
(integer) 1
redis> SPOP myset
"one"
redis> SMEMBERS myset
1) "three"
2) "two"
redis> SADD myset "four"
(integer) 1
redis> SADD myset "five"
(integer) 1
redis> SPOP myset 3
1) "five"
2) "four"
3) "two"
redis> SMEMBERS myset
1) "three"
redis>
查询
scard:查询元素个数
作用
返回集合中元素的数量
语法
> scard key
返回值
- 集合的数量。
- 当集合 key 不存在时,返回 0 。
实例
redis 127.0.0.1:6379> SADD myset "hello"
(integer) 1
redis 127.0.0.1:6379> SADD myset "foo"
(integer) 1
redis 127.0.0.1:6379> SCARD myset
(integer) 2
Sismember:元素是否在集合中
作用
- 判断成员元素是否是集合的成员。
语法
SISMEMBER key value
返回值
- 如果成员元素是集合的成员,返回 1 。
- 如果成员元素不是集合的成员,或 key 不存在,返回 0 。
实例
redis 127.0.0.1:6379> SADD myset1 "hello"
(integer) 1
redis 127.0.0.1:6379> SISMEMBER myset1 "hello"
(integer) 1
redis 127.0.0.1:6379> SISMEMBER myset1 "world"
(integer) 0
Srandmember:随机从集合返回指定个数元素
作用
Redis Srandmember 命令用于返回集合中的一个随机元素。
从 Redis 2.6 版本开始, Srandmember 命令接受可选的 count 参数:
- 如果 count 为正数,且小于集合基数,那么命令返回一个包含 count 个元素的数组,数组中的元素各不相同。如果 count 大于等于集合基数,那么返回整个集合。
- 如果 count 为负数,那么命令返回一个数组,数组中的元素可能会重复出现多次,而数组的长度为 count 的绝对值。
该操作和 SPOP 相似,但 SPOP 将随机元素从集合中移除并返回,而 Srandmember 则仅仅返回随机元素,而不对集合进行任何改动。
语法
redis 127.0.0.1:6379> SRANDMEMBER KEY [count]
返回值
- 只提供集合 key 参数时,返回一个元素;如果集合为空,返回 nil 。
- 如果提供了 count 参数,那么返回一个数组;如果集合为空,返回空数组。
实例
redis> SADD myset one two three
(integer) 3
redis> SRANDMEMBER myset
"one"
redis> SRANDMEMBER myset 2
1) "three"
2) "one"
redis> SRANDMEMBER myset -5
1) "one"
2) "one"
3) "one"
4) "one"
5) "one"
redis>
# 添加元素
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)
smembers
作用
- 返回集合中的所有的成员。
- 不存在的集合 key 被视为空集合。
语法
redis 127.0.0.1:6379> SMEMBERS key
返回值
集合中的所有成员。
实例
redis 127.0.0.1:6379> SADD myset1 "hello"
(integer) 1
redis 127.0.0.1:6379> SADD myset1 "world"
(integer) 1
redis 127.0.0.1:6379> SMEMBERS myset1
1) "World"
2) "Hello"
smembers和lrange以及hgetall都是比较中的命令,如果元素过多就肯能阻塞redis,这时候可以用sscan完成
集合间操作
sinter:交集
作用
- 返回一个集合的全部成员,该集合是所有给定集合的交集。\
- 不存在的集合 key 被视为空集。 当给定集合当中有一个空集时,结果也为空集(根据集合运算定律)。
语法
sinter key key1...keyn
返回值
交集成员的列表。
时间复杂度
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"
Sinterstore: 并集并存储在指定集合
作用
- Redis Sinterstore 命令将给定集合之间的交集存储在指定的集合中。
- 如果指定的集合已经存在,则将其覆盖
语法
redis 127.0.0.1:6379> SINTERSTORE DESTINATION_KEY KEY KEY1..KEYN
返回值
- 返回存储交集的集合的元素数量。
实例
redis 127.0.0.1:6379> SADD myset1 "hello"
(integer) 1
redis 127.0.0.1:6379> SADD myset1 "foo"
(integer) 1
redis 127.0.0.1:6379> SADD myset1 "bar"
(integer) 1
redis 127.0.0.1:6379> SADD myset2 "hello"
(integer) 1
redis 127.0.0.1:6379> SADD myset2 "world"
(integer) 1
redis 127.0.0.1:6379> SINTERSTORE myset myset1 myset2
(integer) 1
redis 127.0.0.1:6379> SMEMBERS myset
1) "hello"
sunion:并集
作用
- 返回给定集合的并集
语法
SUNION KEY KEY1..KEYN
返回值
并集成员的列表。
实例
redis> SMEMBERS songs
1) "Billie Jean"
redis> SMEMBERS my_songs
1) "Believe Me"
redis> SUNION songs my_songs
1) "Billie Jean"
2) "Believe Me"
sunionstore :并集并存储
实例
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"
Sdiff:差集
作用
对于两个集合:返回的值只存在于第一个但是不存在第二个集合中的那就是差集
返回值
交集成员的列表
实例
redis 127.0.0.1:6379> SADD myset "hello"
(integer) 1
redis 127.0.0.1:6379> SADD myset "foo"
(integer) 1
redis 127.0.0.1:6379> SADD myset "bar"
(integer) 1
redis 127.0.0.1:6379> SADD myset2 "hello"
(integer) 1
redis 127.0.0.1:6379> SADD myset2 "world"
(integer) 1
redis 127.0.0.1:6379> SDIFF myset myset2
1) "foo"
2) "bar"
内部编码
集合类型的内部编码有两种:
- intset(整数集合):当集合中的元素都是整数且元素个数小于set-maxintset-entries配置(默认512个)时,Redis会选用intset来作为集合的内部实现,从而减少内存的使用。
- hashtable(哈希表):当集合类型无法满足intset的条件时,Redis会使用hashtable作为集合的内部实现。
使用场景
- sadd :标签
- spop/sandmember:生成随机数,比如抽奖
- sadd/sinter:社交需求
标签
例如一个用户可能对娱乐、体育比较感兴趣,另一个用户可能对历史、新闻比较感兴趣,这些兴趣点就是标签。有了这些数据就可以得到喜欢同一个标签的人,以及用户的共同喜好的标签,这些数据对于用户体验以及增强用户黏度比较重要。
例如一个电子商务的网站会对不同标签的用户做不同类型的推荐,比如对数码产品比较感兴趣的人,在各个页面或者通过邮件的形式给他们推荐最新的数码产品,通常会为网站带来更多的利益。
- 给用户添加标签
sadd user:1:tags tag1 tag2 tag5 sadd user:2:tags tag2 tag3 tag5
- 给标签添加用户
sadd tag1:users user:1 user:3 sadd tag2:users user:1 user:2 user:3
- 删除用户下的标签
srem user:1:tags tag1 tag5
- 删除标签下的用户
srem tag1:users user:1 srem
- 计算用户共同感兴趣的标签