Redis集合Set #
一、集合概述 #
1.1 什么是集合 #
Redis集合是字符串的无序集合:
- 无序:元素没有顺序
- 唯一:不允许重复元素
- 高效:O(1)时间复杂度的添加、删除、查找
text
集合结构:
┌─────────────────────────────────────────────┐
│ Set(哈希表实现) │
│ ┌─────┐ ┌─────┐ ┌─────┐ │
│ │ "a" │ │ "b" │ │ "c" │ │
│ └─────┘ └─────┘ └─────┘ │
│ │
│ 特点: │
│ - 自动去重 │
│ - 快速判断元素是否存在 │
│ - 支持集合运算 │
└─────────────────────────────────────────────┘
最大元素数:2^32 - 1(约40亿)
1.2 集合编码 #
text
Redis集合的编码方式:
1. intset(整数集合)
┌─────────────────────────────────────────────┐
│ 所有元素都是整数 │
│ 元素数量不超过512个 │
│ 内存连续,节省空间 │
└─────────────────────────────────────────────┘
2. hashtable(哈希表)
┌─────────────────────────────────────────────┐
│ 元素包含非整数 │
│ 或元素数量超过512个 │
│ O(1)时间复杂度 │
└─────────────────────────────────────────────┘
二、基本操作 #
2.1 添加元素 #
bash
# SADD: 添加元素
SADD myset "a"
# (integer) 1 添加成功
SADD myset "b" "c" "d"
# (integer) 3 添加成功数量
# 添加重复元素
SADD myset "a"
# (integer) 0 已存在,不添加
2.2 查看集合 #
bash
# SMEMBERS: 获取所有元素
SADD myset "a" "b" "c"
SMEMBERS myset
# 1) "a"
# 2) "b"
# 3) "c"
# SCARD: 获取元素数量
SCARD myset
# (integer) 3
# SISMEMBER: 检查元素是否存在
SISMEMBER myset "a"
# (integer) 1 存在
SISMEMBER myset "x"
# (integer) 0 不存在
# SMISMEMBER: 批量检查(Redis 6.2+)
SMISMEMBER myset "a" "b" "x"
# 1) (integer) 1
# 2) (integer) 1
# 3) (integer) 0
2.3 删除元素 #
bash
# SREM: 删除元素
SREM myset "a"
# (integer) 1 删除成功
SREM myset "x"
# (integer) 0 元素不存在
# 删除多个元素
SREM myset "b" "c"
# (integer) 2
# SPOP: 随机弹出元素
SADD myset "a" "b" "c" "d"
SPOP myset
# "c" 随机返回一个元素
# 弹出多个元素
SPOP myset 2
# 1) "a"
# 2) "d"
2.4 随机元素 #
bash
# SRANDMEMBER: 随机获取元素(不移除)
SADD myset "a" "b" "c" "d" "e"
# 随机获取1个
SRANDMEMBER myset
# "b"
# 随机获取多个(可能重复)
SRANDMEMBER myset 3
# 1) "a"
# 2) "c"
# 3) "a"
# 随机获取多个(不重复)
SRANDMEMBER myset -3
# 1) "d"
# 2) "e"
# 3) "b"
# 获取数量超过集合大小
SRANDMEMBER myset 10
# 返回所有元素(不重复)
三、集合运算 #
3.1 交集 #
bash
# 准备数据
SADD set1 "a" "b" "c" "d"
SADD set2 "c" "d" "e" "f"
SADD set3 "c" "d" "g"
# SINTER: 获取交集
SINTER set1 set2
# 1) "c"
# 2) "d"
# 多个集合的交集
SINTER set1 set2 set3
# 1) "c"
# 2) "d"
# SINTERCARD: 获取交集元素数量(Redis 7.0+)
SINTERCARD 2 set1 set2
# (integer) 2
# SINTERSTORE: 保存交集到新集合
SINTERSTORE result set1 set2
# (integer) 2
SMEMBERS result
# 1) "c"
# 2) "d"
3.2 并集 #
bash
# SUNION: 获取并集
SUNION set1 set2
# 1) "a"
# 2) "b"
# 3) "c"
# 4) "d"
# 5) "e"
# 6) "f"
# 多个集合的并集
SUNION set1 set2 set3
# 1) "a"
# 2) "b"
# 3) "c"
# 4) "d"
# 5) "e"
# 6) "f"
# 7) "g"
# SUNIONSTORE: 保存并集到新集合
SUNIONSTORE result set1 set2
# (integer) 6
3.3 差集 #
bash
# SDIFF: 获取差集(set1 - set2)
SDIFF set1 set2
# 1) "a"
# 2) "b"
# 多个集合的差集
# set1 - set2 - set3
SDIFF set1 set2 set3
# 1) "a"
# 2) "b"
# SDIFFSTORE: 保存差集到新集合
SDIFFSTORE result set1 set2
# (integer) 2
SMEMBERS result
# 1) "a"
# 2) "b"
3.4 集合运算图解 #
text
交集 SINTER:
┌─────────────────────────────────────────────┐
│ set1 set2 │
│ ┌───────┐ ┌───────┐ │
│ │ a b │ │ e f │ │
│ │ ┌───┼────┼───┐ │ │
│ │ │ c │ d │ c │ d │ ← 交集 │
│ │ └───┼────┼───┘ │ │
│ └───────┘ └───────┘ │
└─────────────────────────────────────────────┘
并集 SUNION:
┌─────────────────────────────────────────────┐
│ set1 set2 │
│ ┌───────┐ ┌───────┐ │
│ │ a b │ │ e f │ │
│ │ c │ d │ c d │ ← 全部元素 │
│ └───────┴────┴───────┘ │
└─────────────────────────────────────────────┘
差集 SDIFF:
┌─────────────────────────────────────────────┐
│ set1 set2 │
│ ┌───────┐ ┌───────┐ │
│ │ a b │ ← │ e f │ │
│ │ c │ d │ c d │ │
│ └───────┘ └───────┘ │
│ set1 - set2 = {a, b} │
└─────────────────────────────────────────────┘
四、移动元素 #
bash
# SMOVE: 将元素从一个集合移动到另一个集合
SADD set1 "a" "b" "c"
SADD set2 "x" "y"
SMOVE set1 set2 "a"
# (integer) 1 移动成功
SMEMBERS set1
# 1) "b"
# 2) "c"
SMEMBERS set2
# 1) "x"
# 2) "y"
# 3) "a"
# 移动不存在的元素
SMOVE set1 set2 "notexist"
# (integer) 0
五、扫描集合 #
bash
# SSCAN: 迭代扫描集合元素
SADD myset "a" "b" "c" "d" "e" "f" "g"
# 扫描
SSCAN myset 0
# 1) "0" # 下一个游标(0表示结束)
# 2) 1) "a"
# 2) "b"
# 3) "c"
# 带数量
SSCAN myset 0 COUNT 3
# 1) "3"
# 2) 1) "a"
# 2) "b"
# 3) "c"
# 带模式
SSCAN myset 0 MATCH a*
# 1) "0"
# 2) 1) "a"
六、应用场景 #
6.1 标签系统 #
bash
# 文章标签
SADD article:1001:tags "redis" "database" "nosql"
SADD article:1002:tags "redis" "cache"
# 获取文章标签
SMEMBERS article:1001:tags
# 查找有特定标签的文章
SADD tag:redis:articles 1001 1002
SADD tag:database:articles 1001
# 查找同时有多个标签的文章
SINTER tag:redis:articles tag:database:articles
# 1) "1001"
6.2 社交关系 #
bash
# 用户关注
SADD user:1001:following 1002 1003 1004
SADD user:1002:following 1001 1003
# 用户粉丝
SADD user:1001:followers 1002
# 共同关注
SINTER user:1001:following user:1002:following
# 1) "1003"
# 我关注的人也关注了他
SINTER user:1001:following user:1002:followers
# 可能认识的人
SDIFF user:1002:following user:1001:following
6.3 抽奖系统 #
bash
# 添加参与者
SADD lottery:2024 user:1001 user:1002 user:1003 user:1004
# 查看参与者数量
SCARD lottery:2024
# (integer) 4
# 抽取1个中奖者(移除)
SPOP lottery:2024
# "user:1003"
# 抽取多个中奖者(不移除)
SRANDMEMBER lottery:2024 2
# 1) "user:1001"
# 2) "user:1004"
6.4 去重 #
bash
# 已读消息去重
SADD user:1001:read:messages msg:1 msg:2 msg:3
# 检查是否已读
SISMEMBER user:1001:read:messages msg:1
# (integer) 1
# 标记已读
SADD user:1001:read:messages msg:4
# UV统计(精确)
SADD page:home:uv user:1001 user:1002 user:1003
SCARD page:home:uv
# (integer) 3
6.5 商品筛选 #
bash
# 商品属性
SADD product:1001:color "red" "blue"
SADD product:1001:brand "nike"
SADD product:1001:size "M" "L"
SADD product:1002:color "red" "green"
SADD product:1002:brand "adidas"
# 红色商品
SADD color:red:products 1001 1002
# Nike商品
SADD brand:nike:products 1001
# 红色Nike商品
SINTER color:red:products brand:nike:products
# 1) "1001"
七、性能优化 #
7.1 避免大集合 #
bash
# 不推荐:超大集合
SADD huge:set item1 item2 ... item1000000
# 推荐:分片集合
SADD small:set:1 item1 item2 ... item10000
SADD small:set:2 item10001 item10002 ... item20000
7.2 使用SSCAN代替SMEMBERS #
bash
# 不推荐:获取所有元素
SMEMBERS myset # 数据量大时阻塞
# 推荐:迭代扫描
SSCAN myset 0
7.3 集合运算优化 #
bash
# 集合运算时,小集合放前面
SINTER small_set large_set
# 使用SINTERCARD代替SINTER + SCARD
SINTERCARD 2 set1 set2
八、总结 #
集合操作命令:
| 命令 | 说明 |
|---|---|
| SADD | 添加元素 |
| SREM | 删除元素 |
| SMEMBERS | 获取所有元素 |
| SISMEMBER | 检查元素存在 |
| SCARD | 获取元素数量 |
| SPOP | 随机弹出 |
| SRANDMEMBER | 随机获取 |
集合运算命令:
| 命令 | 说明 |
|---|---|
| SINTER | 交集 |
| SUNION | 并集 |
| SDIFF | 差集 |
| SINTERSTORE | 保存交集 |
| SUNIONSTORE | 保存并集 |
| SDIFFSTORE | 保存差集 |
应用场景:
| 场景 | 实现方式 |
|---|---|
| 标签系统 | SADD + SINTER |
| 社交关系 | SADD + SINTER + SDIFF |
| 抽奖 | SPOP / SRANDMEMBER |
| 去重 | SADD + SISMEMBER |
下一步,让我们学习Redis哈希Hash!
最后更新:2026-03-27