Redis 集合

来源:互联网 发布:保温杯十大排名 知乎 编辑:程序博客网 时间:2024/05/20 01:38

简介

集合(set)类型也是用来保存多个的字符串元素,但和列表类型不一样的是,集合中不允许有重复元素,并且集合中的元素是无序的,不能通过索引下标获取元素。一个集合最多可以存储 2321 个元素。Redis除了支持集合内的增删改查,同时还支持多个集合取交集、并集、差集,合理地使用好集合类型,能在实际开发中解决很多实际问题。

命令

集合内操作

添加元素

SADD

自1.0.0可用。

**时间复杂度:**O(N), N 是被添加的元素的数量。

语法:SADD key member [member …]
说明:

将一个或多个 member 元素加入到集合 key 当中,已经存在于集合的 member 元素将被忽略。

假如 key 不存在,则创建一个只包含 member 元素作成员的集合。

key 不是集合类型时,返回一个错误。

在 Redis 2.4 版本以前的 SADD 命令,都只接受单个 member 值。

返回值:

被添加到集合中的新元素的数量,不包括被忽略的元素。

示例:
127.0.0.1:6379> SADD saddTest add1 add2 add3(integer) 3# 查看集合中所有元素(该命令之后会介绍)127.0.0.1:6379> SMEMBERS saddTest1) "add1"2) "add3"3) "add2"# 添加四个元素,其中两个与之前添加过的元素重复127.0.0.1:6379> SADD saddTest add1 add4 add3 add5(integer) 2 # 只成功添加两个元素(重复的不再添加 )127.0.0.1:6379> SMEMBERS saddTest1) "add3"2) "add2"3) "add4"4) "add5"5) "add1"

删除元素

SREM

自1.0.0可用。

**时间复杂度:**O(N), N 是被添加的元素的数量。

语法:SREM key member [member …]
说明:

移除集合 key 中的一个或多个 member 元素,不存在的 member 元素会被忽略。

key 不是集合类型,返回一个错误。

在 Redis 2.4 版本以前的 SREM 命令,都只接受单个 member 值。

返回值:

被成功移除的元素的数量,不包括被忽略的元素。

示例:
# 删除三个元素,其中 sadd7 不存在127.0.0.1:6379> SREM saddTest add3 add5 add7(integer) 2127.0.0.1:6379> SMEMBERS saddTest1) "add4"2) "add1"3) "add2"# 执行该操作的不是集合元素127.0.0.1:6379> SREM embstrKey a(error) WRONGTYPE Operation against a key holding the wrong kind of value

计算元素个数

SCARD

自1.0.0可用。

**时间复杂度:**O(1)。

语法:SCARD key
说明:

返回集合 key 的基数(集合中元素的数量)。

返回值:

集合的基数。

key 不存在时,返回 0

示例:
127.0.0.1:6379> SCARD saddTest(integer) 3# key 不存在返回 0127.0.0.1:6379> SCARD add(integer) 0# key 类型不是集合时会报错127.0.0.1:6379> SCARD embstrKey(error) WRONGTYPE Operation against a key holding the wrong kind of value

SCARD 命令不会遍历集合所有元素,而是直接使用 Redis 内部的变量来获取集合长度。

判断元素是否存在集合中

SISMEMBER

自1.0.0可用。

**时间复杂度:**O(1)。

语法:SISMEMBER key member
说明:

判断 member 元素是否集合 key 的成员。

返回值:

如果 member 元素是集合的成员,返回 1

如果 member 元素不是集合的成员,或 key 不存在,返回 0

示例:
127.0.0.1:6379> SISMEMBER saddTest add1(integer) 1#  add7  元素不存在127.0.0.1:6379> SISMEMBER saddTest add7(integer) 0# key 不存在127.0.0.1:6379> SISMEMBER nonSet a(integer) 0# key 类型不是集合127.0.0.1:6379> SISMEMBER embstrKey a(error) WRONGTYPE Operation against a key holding the wrong kind of value

随机从集合中返回指定个数的元素

SRANDMEMBER

自1.0.0可用。

时间复杂度:只提供 key 参数时为 O(1) 。

如果提供了 count 参数,那么为 O(N) ,N 为返回数组的元素个数。

语法:SRANDMEMBER key [count]
说明:

如果命令执行时,只提供了 key 参数,那么返回集合中的一个随机元素。

从 Redis 2.6 版本开始, SRANDMEMBER 命令接受可选的 count 参数:

  • 如果 count 为正数,且小于集合基数,那么命令返回一个包含 count 个元素的数组,数组中的元素各不相同。如果 count 大于等于集合基数,那么返回整个集合。
  • 如果 count 为负数,那么命令返回一个数组,数组中的元素可能会重复出现多次,而数组的长度为 count 的绝对值。

该操作和 SPOP 相似,但 SPOP 将随机元素从集合中移除并返回,而 SRANDMEMBER 则仅仅返回随机元素,而不对集合进行任何改动。

返回值:

只提供 key 参数时,返回一个元素;如果集合为空,返回 nil

如果提供了 count 参数,那么返回一个数组;如果集合为空,返回空数组。

示例:
127.0.0.1:6379> SADD languageSet java go python kotlin c lua javascript127.0.0.1:6379> SRANDMEMBER languageSet"kotlin"127.0.0.1:6379> SRANDMEMBER languageSet"go"127.0.0.1:6379> SRANDMEMBER languageSet 31) "go"2) "python"3) "javascript"127.0.0.1:6379> SRANDMEMBER languageSet 31) "c"2) "java"3) "lua"# count 超出 长度时返回所有的元素127.0.0.1:6379>  SRANDMEMBER languageSet 81) "kotlin"2) "c"3) "java"4) "go"5) "lua"6) "python"7) "javascript"127.0.0.1:6379> SRANDMEMBER languageSet -21) "python"2) "kotlin"# key 不存在时返回空集合127.0.0.1:6379> SRANDMEMBER nonKey 2(empty list or set)127.0.0.1:6379>  SRANDMEMBER nonKey(nil)

从集合中随机弹出元素

SPOP

自1.0.0可用。

**时间复杂度:**O(1)。

语法:SPOP key [count]
说明:

移除并返回集合中的一个随机元素。

如果只想获取一个随机元素,但不想该元素从集合中被移除的话,可以使用 SRANDMEMBER 命令。

从 Redis 3.2 版本开始, SPOP 命令接受可选的 count 参数

返回值:

被移除的随机元素。

key 不存在或 key 是空集时,返回 nil

如果提供了 count 参数,那么返回一个数组;如果集合为空,返回空数组。

示例:
127.0.0.1:6379> SMEMBERS languageSet1) "kotlin"2) "c"3) "java"4) "go"5) "javascript"6) "python"7) "lua"# 该命令不支持付费作为参数127.0.0.1:6379> SPOP languageSet -2(error) ERR index out of range127.0.0.1:6379> SPOP languageSet 21) "lua"2) "python"127.0.0.1:6379> SMEMBERS languageSet1) "kotlin"2) "c"3) "java"4) "go"5) "javascript"127.0.0.1:6379> SPOP nonSet 2(empty list or set)127.0.0.1:6379> SPOP nonSet(nil)

srandmemberspop 都是随机从集合选出元素,两者不同的是 spop 命令执行后,元素会从集合中删除,而 srandmember 不会。

获取所有元素

SMEMBERS

自1.0.0可用。

**时间复杂度:**O(N), N 为集合的基数。

语法:SMEMBERS key
说明:

返回集合 key 中的所有成员。

不存在的 key 被视为空集合。

这与运行只有 key 参数的 SINTER 命令效果相同。

返回值:

集合中的所有成员,key 不存在返回空集合。

示例:
127.0.0.1:6379> SISMEMBER saddTest add1(integer) 1#  add7  元素不存在127.0.0.1:6379> SISMEMBER saddTest add7(integer) 0# key 不存在127.0.0.1:6379> SISMEMBER nonSet a(integer) 0# key 类型不是集合127.0.0.1:6379> SISMEMBER embstrKey a(error) WRONGTYPE Operation against a key holding the wrong kind of value

smemberslrangehgetall 都属于比较重的命令,如果元素过多存在阻塞Redis的可能性,这时候可以使用 sscan (在 Redis 概览 中有介绍)来完成。

集合间操作

交集

SINTER

自1.0.0可用。

时间复杂度:最差情况:O(N * M), N 为给定集合当中基数最小的集合, M 为给定集合的个数。

语法:SINTER key [key …]
说明:

返回一个集合的全部成员,该集合是所有给定集合的交集。

不存在的 key 被视为空集。

当给定集合当中有一个空集时,结果也为空集(根据集合运算定律)。

返回值:

交集成员的列表。

示例:
127.0.0.1:6379> SINTER languageSet1) "kotlin"2) "c"3) "java"4) "go"5) "javascript"127.0.0.1:6379> SADD loveLanguageSet java c# c++ kotlin(integer) 4127.0.0.1:6379> SINTER languageSet loveLanguageSet1) "kotlin"2) "java"# 不存在的 key 被视为空集127.0.0.1:6379> SINTER languageSet nonSet(empty list or set)

并集

SUNION

自1.0.0可用。

**时间复杂度:**O(N), N 是所有给定集合的成员数量之和。

语法:SUNION key [key …]
说明:

返回一个集合的全部成员,该集合是所有给定集合的并集。

不存在的 key 被视为空集。

返回值:

并集成员的列表。

示例:
127.0.0.1:6379> SUNION languageSet nonSet loveLanguageSet1) "kotlin"2) "c"3) "c++"4) "c#"5) "java"6) "go"7) "javascript"

差集

SDIFF

自1.0.0可用。

**时间复杂度:**O(N), N 是所有给定集合的成员数量之和。

语法:SDIFF key [key …]
说明:

返回一个集合的全部成员,该集合是所有给定集合之间的差集。

不存在的 key 被视为空集。

返回值:

一个包含差集成员的列表。

示例:
127.0.0.1:6379> SMEMBERS languageSet1) "kotlin"2) "c"3) "java"4) "go"5) "javascript"127.0.0.1:6379> SMEMBERS loveLanguageSet1) "kotlin"2) "c++"3) "c#"4) "java"# 一个集合与不存在 key 或者空集合的差集还是该集合本身127.0.0.1:6379> SDIFF languageSet nonSet1) "c"2) "kotlin"3) "go"4) "java"5) "javascript"127.0.0.1:6379> SDIFF languageSet loveLanguageSet1) "c"2) "javascript"3) "go"

存储集合运算结果

SINTER 交集、SUNION 并集、SDIFF 差集在集合较多时运行比较耗时,所以 Redis 提供了原命令 +STORE 的命令可以用来将运算结果进行保存。

SINTERSTORE

自1.0.0可用。

*时间复杂度:**O(N M), N 为给定集合当中基数最小的集合, M 为给定集合的个数。

语法:SINTERSTORE destination key [key …]
说明:

这个命令类似于 SINTER 命令,但它将结果保存到 destination 集合,而不是简单地返回结果集。

如果 destination 集合已经存在,则将其覆盖。

destination 可以是 key 本身。

返回值:

结果集中的成员数量。

示例:
127.0.0.1:6379> SINTERSTORE sinterStoreTest languageSet loveLanguageSet(integer) 2127.0.0.1:6379> SMEMBERS sinterStoreTest1) "kotlin"2) "java"

SUNIONSTORE

自1.0.0可用。

**时间复杂度:**O(N), N 是所有给定集合的成员数量之和。

语法:SUNIONSTORE destination key [key …]
说明:

这个命令类似于 SUNION 命令,但它将结果保存到 destination 集合,而不是简单地返回结果集。

如果 destination 已经存在,则将其覆盖。

destination 可以是 key 本身。

返回值:

结果集中的成员数量。

示例:
127.0.0.1:6379> SUNIONSTORE sunionStoryTest languageSet nonSet loveLanguageSet(integer) 7127.0.0.1:6379> SMEMBERS sunionStoryTest1) "kotlin"2) "c"3) "c++"4) "c#"5) "java"6) "go"7) "javascript"

SDIFFSTORE

自1.0.0可用。

**时间复杂度:**O(N), N 是所有给定集合的成员数量之和。

语法:SDIFFSTORE destination key [key …]
说明:

这个命令的作用和 SDIFF 类似,但它将结果保存到 destination 集合,而不是简单地返回结果集。

如果 destination 集合已经存在,则将其覆盖。

destination 可以是 key 本身。

返回值:

结果集中的元素数量。

示例:
127.0.0.1:6379> SDIFFSTORE sdiffTest languageSet loveLanguageSet(integer) 3127.0.0.1:6379> SMEMBERS sdiffTest1) "c"2) "javascript"3) "go"

内部编码

集合类型的内部编码有两种:

  • intset(整数集合):当集合中的元素都是整数且元素个数小于 set-maxintset-entries 配置(默认512个)时,Redis 会选用 intset 来作为集合的内部实现,从而减少内存的使用。

  • hashtable(哈希表):当集合类型无法满足 intset 的条件时,Redis 会使用 hashtable 作为集合的内部实现。

    1. 当元素个数较少且都为整数时,内部编码为 intset:
127.0.0.1:6379> SADD testIntset 1 2 3 4 5 6(integer) 6127.0.0.1:6379> OBJECT ENCODING testIntset"intset"
  1. 当元素个数超过512个,内部编码变为 hashtable:【这里使用 python 进行测试】
import redisr = redis.StrictRedis(host='127.0.0.1', password='admin123', port=6379, db=0)num = 512key = "intListTest" + str(num)r.delete(key)for i in range(num):r.sadd(key, i)# 可以使用这个命令查询内部编码print(key)print(r.scard(key))print(r.object("ENCODING", key))

输出结果:

intListTest512512b'intset'

我们将 num 改为 513 输出结果:

intListTest512512b'intset'
  1. 当某个元素不为整数时,内部编码也会变为 hashtable:
127.0.0.1:6379> SADD testIntset a(integer) 1127.0.0.1:6379>  OBJECT ENCODING testIntset"hashtable"

使用场景

  • sdd=Tagging(标签)
  • spop/srandmember=Random item(生成随机数,比如抽奖)
  • sadd+sinter=Social Graph(社交需求)

我是广告

本人 Redis 方面的讲座已经上线快去看看有没有你感兴趣的吧(说不定会有优惠哟~~数量有限要抓紧呀):

提升职业竞争力的必备知识 Redis 之初识

提升职业竞争力的必备知识 Redis 之高级特性

提升职业竞争力的必备知识 Redis 之缓存与Session共享

提升职业竞争力的必备知识 Redis 之排行榜与附近的人

原创粉丝点击