Redis 常见数据类型-Set 类型

Redis 常见数据类型-Set 类型

七月 09, 2025 次阅读

类型简介

集合类型也是保存多个字符串类型的元素的,但和列表类型不同的是,集合中 1)元素之间是⽆序的 2)元素不允许重复,
⼀个集合中最多可以存储 $2^{32}$ - 1 个元素。Redis 除了⽀持集合内的增删查改操作,同时还⽀持多个集合取交集、并集、差集,合理
地使⽤好集合类型,能在实际开发中解决很多问题

相关指令如下:

相关指令

sadd

命令格式:

SADD key member [member ...]

将一个或多个元素添加到 set 中,重复定义的元素是无法添加到 set 中的

时间复杂度:O(1)

返回值:本次添加成功的个数

使用示例:

# 预期添加 5 个元素
127.0.0.1:6379> sadd k1 1 2 3 3 4
# 元素3被重复添加,只能添加一个
(integer) 4
127.0.0.1:6379> smembers k1
1) "1"
2) "2"
3) "3"
4) "4"

smembers

命令格式:

SMEMBERS key

获取—个 set 中的所有元素,元素间的顺序是无序的

时间复杂度:O(N)

返回值:所有元素的列表

使用示例:

127.0.0.1:6379> sadd k1 1 2 3 4
(integer) 4
127.0.0.1:6379> smembers k1
1) "1"
2) "2"
3) "3"
4) "4"

sismember

命令格式:

SISMEMBER key member

判断一个元素是否在 set 中

时间复杂度:O(1)

返回值:1表示存在,0表示不存在

使用示例:

127.0.0.1:6379> sadd k1 1 2 3 4
(integer) 4
# 查询元素 2 存在
127.0.0.1:6379> sismember k1 2
(integer) 1
# 查询元素 5 不存在
127.0.0.1:6379> sismember k1 5
(integer) 0

scard

命令格式:

SCARD key

获取一个 set 的基数,即 set 中的元素个数

时间复杂度:O(1)

返回值:set 中元素的个数

使用示例:

127.0.0.1:6379> sadd k1 1 2 3 4
(integer) 4
127.0.0.1:6379> scard k1
(integer) 4

spop

从set 中删除并返回—个或者多个元素。注意,由于 set 内的元素是无序的,所以取出哪个元素实际是
未定义行为,即可以看作随机的

命令格式:

SPOP key [count]

时间复杂度:O(N) n表示count

返回值:取出的元素

使用示例:

127.0.0.1:6379> sadd k1 1 2 3 4 5 6
(integer) 6
# 默认删除一个随机元素
127.0.0.1:6379> spop k1
"5"
# 删除两个随机元素
127.0.0.1:6379> spop k1 2
1) "4"
2) "6"
# 剩余元素
127.0.0.1:6379> smembers k1
1) "1"
2) "2"
3) "3"

smove

将一个元素从源 set 取出并放到目的 set 中

命令格式:

SMOVE source destination member

时间复杂度:O(1)

返回值:1表示移动成功,0表示移动失败

使用示例:

127.0.0.1:6379> sadd k1 1 2 3 4
(integer) 4
# 依次将 k1 中的所有元素移动到 k2 中
127.0.0.1:6379> smove k1 k2 3
(integer) 1
127.0.0.1:6379> smove k1 k2 4
(integer) 1
127.0.0.1:6379> smove k1 k2 2
(integer) 1
127.0.0.1:6379> smove k1 k2 1
(integer) 1
# k1 中的元素都被移动到 k2 中
127.0.0.1:6379> smembers k1
(empty array)
127.0.0.1:6379> smembers k2
1) "1"
2) "2"
3) "3"
4) "4"
127.0.0.1:6379> sadd k1 1
(integer) 1
127.0.0.1:6379> smove k1 k2 1
(integer) 1
# 移动相同的元素到 k2 中虽然移动成功,但因为 k2 中已经有该元素了,故 k2 无变化
127.0.0.1:6379> smembers k2
1) "1"
2) "2"
3) "3"
4) "4"

srem

该指令用于将指定元素从 set 中删除

命令格式:

SREM key member [member ...]

时间复杂度:O(N),N 表示要删除的元素个数

返回值:本次操作被删除的元素个数

使用示例:

127.0.0.1:6379> sadd k1 1 2 3 4 5
(integer) 5
127.0.0.1:6379> srem k1 1 2 3
(integer) 3
127.0.0.1:6379> srem k1 4 4 4
(integer) 1
127.0.0.1:6379> srem k1 6 7
(integer) 0

集合间操作

sinter

该指令用于获取给定 set 的交集中的元素

命令格式:

SINTER key [key ...]

时间复杂度:O(N * M), N 是最小的集合元素个数. M 是集合个数.

返回值:交集的元素

使用示例:

127.0.0.1:6379> sadd k1 1 2 3 4
(integer) 4
127.0.0.1:6379> sadd k2 2 3 4 5
(integer) 4
127.0.0.1:6379> sadd k3 3 4 5 6
(integer) 4
127.0.0.1:6379> sinter k1 k2 k3
1) "3"
2) "4"

下面是针对该时间复杂度的讨论:

sinterstore

该指令用于获取给定 set 的交集中的元素并保存到目标 set 中

指令格式:

SINTERSTORE destination key [key ...]

时间复杂度:O(N * M), N 是最小的集合元素个数. M 是集合个数.

返回值:交集的元素个数

使用示例:

127.0.0.1:6379> sadd k1 1 2 3 4
(integer) 4
127.0.0.1:6379> sadd k2 2 3 4 5
(integer) 4
127.0.0.1:6379> sadd k3 3 4 5 6
(integer) 4
127.0.0.1:6379> sinterstore k4 k1 k2 k3
(integer) 2
127.0.0.1:6379> smembers k4
1) "3"
2) "4"

sunion、sunionstore、sdiff、sdiffstore

这四个命令和上面的 sinter 和 sinterstore 指令类似,union 用于求并集,diff 用于求差集,故不再赘述

set 相关指令汇总表

命令 时间复杂度
sadd key element [element …] O(k),k 是元素个数
srem key element [element …] O(k),k 是元素个数
scard key O(1)
sismember key element O(1)
srandmember key [count] O(n),n 是 count
spop key [count] O(n),n 是 count
smembers key O(k),k 是元素个数
sinter key [key …] / sinterstore O(m * k),k 是几个集合中元素最小的个数,m 是键个数
sunion key [key …] / sunionstore O(k),k 是多个集合的元素个数总和
sdiff key [key …] / sdiffstore O(k),k 是多个集合的元素个数总和

内部编码

2.5.4 内部编码

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

  • intset(整数集合): 当集合中的元素都是整数并且元素的个数小于 set-max-intset-entries 配置(默认 512 个)时,Redis 会选用 intset 来作为集合的内部实现,从而减少内存的使用。
  • hashtable(哈希表): 当集合类型无法满足 intset 的条件时,Redis 会使用 hashtable 作为集合的内部实现。

示例

  1. 当元素个数较少并且都为整数时,内部编码为 intset
127.0.0.1:6379> sadd setkey 1 2 3 4
(integer) 4
127.0.0.1:6379> object encoding setkey
"intset"
  1. 当元素个数超过 512 个,内部编码为 hashtable
127.0.0.1:6379> sadd setkey 1 2 3 4 ... 513
(integer) 513
127.0.0.1:6379> object encoding setkey
"hashtable"
  1. 当存在元素不是整数时,内部编码为 hashtable
127.0.0.1:6379> sadd setkey a
(integer) 1
127.0.0.1:6379> object encoding setkey
"hashtable"

应用场景

集合类型在标签系统中的应用

集合类型在标签(tag)系统中有着典型的使用场景,例如:

  • 用户兴趣标签(娱乐、体育、历史、新闻等)
  • 基于标签的用户分析(共同兴趣、个性化推荐)
  • 电子商务的个性化产品推荐

实现标签功能的Redis命令演示

1. 给用户添加标签
sadd user:1:tags tag1 tag2 tag5
sadd user:2:tags tag2 tag3 tag5
...
sadd user:k:tags tag1 tag2 tag4
2. 给标签添加用户
sadd tag1:users user:1 user:3
sadd tag2:users user:1 user:2 user:3
...
sadd tagk:users user:1 user:4 user:9 user:28
3. 删除用户下的标签
srem user:1:tags tag1 tag5
4. 删除标签下的用户
srem tag1:users user:1
srem tag5:users user:1
5. 计算用户的共同兴趣标签
sinter user:1:tags user:2:tags

应用价值

这种实现方式可以:

  1. 发现喜欢同一标签的用户群体
  2. 分析用户的共同兴趣标签
  3. 为个性化推荐系统提供数据支持
  4. 增强用户体验和用户黏度