集合类型概述
Redis 集合是字符串的无序集合,集合中的元素是唯一的,不允许重复。集合支持多种集合运算,如交集、并集、差集等。集合最多可以包含 2^32 - 1 个元素。
集合结构示意图
A
B
C
D
E
特点:无序、唯一、支持集合运算
📝 基本操作命令
集合类型的基础增删查操作:
命令 | 描述 | 示例 |
---|---|---|
SADD key member [member ...] |
添加元素到集合 | SADD myset "hello" "world" |
SREM key member [member ...] |
从集合中删除元素 | SREM myset "hello" |
SISMEMBER key member |
检查元素是否在集合中 | SISMEMBER myset "world" |
SMEMBERS key |
获取集合所有元素 | SMEMBERS myset |
SCARD key |
获取集合元素数量 | SCARD myset |
SPOP key [count] |
随机弹出元素 | SPOP myset 2 |
SRANDMEMBER key [count] |
随机获取元素(不删除) | SRANDMEMBER myset 3 |
基本操作示例:
# 创建集合并添加元素 SADD fruits "apple" "banana" "orange" SADD fruits "apple" # 重复元素不会被添加 # 查看集合信息 SCARD fruits # 返回: 3 SMEMBERS fruits # 返回: ["apple", "banana", "orange"] # 检查元素是否存在 SISMEMBER fruits "apple" # 返回: 1 (存在) SISMEMBER fruits "grape" # 返回: 0 (不存在) # 随机操作 SRANDMEMBER fruits # 随机返回一个元素 SRANDMEMBER fruits 2 # 随机返回2个元素 SPOP fruits # 随机弹出一个元素 # 删除元素 SREM fruits "banana" SMEMBERS fruits # 返回: ["apple", "orange"]
🔄 集合运算命令
Redis 支持多种集合运算操作:
命令 | 描述 | 示例 |
---|---|---|
SINTER key [key ...] |
计算集合交集 | SINTER set1 set2 |
SINTERSTORE destination key [key ...] |
计算交集并存储 | SINTERSTORE result set1 set2 |
SUNION key [key ...] |
计算集合并集 | SUNION set1 set2 |
SUNIONSTORE destination key [key ...] |
计算并集并存储 | SUNIONSTORE result set1 set2 |
SDIFF key [key ...] |
计算集合差集 | SDIFF set1 set2 |
SDIFFSTORE destination key [key ...] |
计算差集并存储 | SDIFFSTORE result set1 set2 |
集合A
集合B
集合运算可视化:交集(重叠部分)、并集(全部)、差集(A-B)
集合运算示例:
# 创建测试集合 SADD programming_languages "Python" "Java" "JavaScript" "Go" SADD web_languages "JavaScript" "PHP" "Python" "Ruby" SADD mobile_languages "Java" "Swift" "Kotlin" "Dart" # 交集运算 SINTER programming_languages web_languages # 返回: ["Python", "JavaScript"] (共同的语言) SINTER programming_languages mobile_languages # 返回: ["Java"] (编程语言和移动开发语言的交集) # 并集运算 SUNION programming_languages web_languages # 返回: ["Python", "Java", "JavaScript", "Go", "PHP", "Ruby"] # 差集运算 SDIFF programming_languages web_languages # 返回: ["Java", "Go"] (编程语言中不是Web语言的) SDIFF web_languages programming_languages # 返回: ["PHP", "Ruby"] (Web语言中不在编程语言集合的) # 存储运算结果 SINTERSTORE common_languages programming_languages web_languages SMEMBERS common_languages # 返回: ["Python", "JavaScript"]
🔍 集合遍历命令
安全遍历大集合的命令:
命令 | 描述 | 示例 |
---|---|---|
SSCAN key cursor [MATCH pattern] [COUNT count] |
迭代集合元素 | SSCAN myset 0 MATCH "user:*" |
集合遍历示例:
# 创建大集合 SADD large_set user:1001 user:1002 user:1003 admin:2001 admin:2002 # 遍历所有元素 SSCAN large_set 0 # 按模式匹配 SSCAN large_set 0 MATCH "user:*" # 返回: 匹配"user:*"模式的元素 # 限制返回数量 SSCAN large_set 0 COUNT 2
🔀 集合间移动
在不同集合之间移动元素:
命令 | 描述 | 示例 |
---|---|---|
SMOVE source destination member |
将元素从源集合移动到目标集合 | SMOVE set1 set2 "element" |
集合移动示例:
# 创建用户状态集合 SADD online_users "user1" "user2" "user3" SADD offline_users "user4" "user5" # 用户上线 SMOVE offline_users online_users "user4" SMEMBERS online_users # 返回: ["user1", "user2", "user3", "user4"] SMEMBERS offline_users # 返回: ["user5"] # 用户下线 SMOVE online_users offline_users "user2" SMEMBERS online_users # 返回: ["user1", "user3", "user4"] SMEMBERS offline_users # 返回: ["user5", "user2"]
实际应用场景
🏷️ 标签系统
使用集合管理文章、用户的标签:
# 文章标签 SADD article:1001:tags "Redis" "数据库" "缓存" "NoSQL" SADD article:1002:tags "Python" "编程" "Web开发" SADD article:1003:tags "Redis" "Python" "教程" # 用户兴趣标签 SADD user:1001:interests "Redis" "Python" "机器学习" SADD user:1002:interests "Java" "Spring" "微服务" # 查找共同标签 SINTER article:1001:tags user:1001:interests # 返回: ["Redis", "Python"] (用户感兴趣的文章标签) # 推荐相关文章(有共同标签的文章) SINTER article:1001:tags article:1003:tags # 返回: ["Redis"] (两篇文章的共同标签) # 获取所有标签 SUNION article:1001:tags article:1002:tags article:1003:tags # 返回: 所有文章的标签集合
👥 好友关系
使用集合管理用户的好友关系:
# 用户好友列表 SADD user:1001:friends "user1002" "user1003" "user1004" "user1005" SADD user:1002:friends "user1001" "user1003" "user1006" "user1007" SADD user:1003:friends "user1001" "user1002" "user1008" # 查找共同好友 SINTER user:1001:friends user:1002:friends # 返回: ["user1003"] (共同好友) # 推荐好友(朋友的朋友,但不是自己的朋友) SUNION user:1002:friends user:1003:friends # 朋友的朋友 SDIFF result user:1001:friends # 排除已有好友 SREM result "user1001" # 排除自己 # 检查是否为好友 SISMEMBER user:1001:friends "user1002" # 返回: 1 (是好友) # 添加/删除好友 SADD user:1001:friends "user1009" # 添加好友 SREM user:1001:friends "user1004" # 删除好友
🎲 抽奖系统
使用集合实现抽奖和去重功能:
# 参与抽奖的用户 SADD lottery:2024:participants "user1001" "user1002" "user1003" "user1004" "user1005" # 随机抽取中奖者 SRANDMEMBER lottery:2024:participants 3 # 随机选择3个中奖者(可重复) SPOP lottery:2024:participants 3 # 随机弹出3个中奖者(不重复) # 查看剩余参与者 SCARD lottery:2024:participants # 剩余参与者数量 SMEMBERS lottery:2024:participants # 剩余参与者列表 # 防止重复参与 SADD lottery:2024:participants "user1006" # 添加新参与者 SADD lottery:2024:participants "user1001" # 重复参与者不会被添加 # 已中奖用户(防止重复中奖) SADD lottery:2024:winners "user1001" "user1003" SDIFF lottery:2024:participants lottery:2024:winners # 未中奖的参与者
🔍 搜索过滤
使用集合实现多条件搜索过滤:
# 商品分类 SADD category:electronics "product1001" "product1002" "product1003" SADD category:books "product2001" "product2002" "product1003" SADD category:clothing "product3001" "product3002" # 商品品牌 SADD brand:apple "product1001" "product1002" SADD brand:samsung "product1003" "product1004" SADD brand:nike "product3001" "product3002" # 价格区间 SADD price:100-500 "product1001" "product2001" "product3001" SADD price:500-1000 "product1002" "product1003" SADD price:1000+ "product1004" "product2002" # 多条件搜索:电子产品 AND 苹果品牌 AND 500-1000价格区间 SINTER category:electronics brand:apple price:500-1000 # 返回: ["product1002"] (满足所有条件的商品) # 或条件搜索:苹果品牌 OR 三星品牌 SUNION brand:apple brand:samsung # 返回: 苹果或三星的所有商品
📊 数据去重
使用集合进行数据去重处理:
# 网站访问者去重 SADD daily:visitors:2024-01-15 "192.168.1.1" "192.168.1.2" "192.168.1.1" SCARD daily:visitors:2024-01-15 # 返回: 2 (去重后的访问者数量) # 邮件订阅者去重 SADD newsletter:subscribers "user1@example.com" "user2@example.com" "user1@example.com" SMEMBERS newsletter:subscribers # 返回: 去重后的邮件列表 # 文章阅读者去重 SADD article:1001:readers "user1001" "user1002" "user1001" SCARD article:1001:readers # 返回: 2 (去重后的阅读者数量) # 合并多天的访问者 SUNIONSTORE weekly:visitors:2024-w3 \ daily:visitors:2024-01-15 \ daily:visitors:2024-01-16 \ daily:visitors:2024-01-17 SCARD weekly:visitors:2024-w3 # 一周内的唯一访问者数量
性能优化建议
- 避免大集合:单个集合元素数量不宜过多(建议小于10万)
- 使用 SSCAN:遍历大集合时使用 SSCAN 而不是 SMEMBERS
- 合理使用运算:集合运算的时间复杂度较高,注意性能
- 批量操作:使用 SADD 的多元素版本减少网络往返
- 选择合适场景:需要去重和集合运算时使用 Set
- 内存优化:Redis 对小集合有特殊的内存优化
集合 vs 其他数据类型
数据类型选择建议:
- Set vs List:Set不允许重复且无序,List允许重复且有序
- Set vs Hash:Set存储单一值,Hash存储键值对
- Set vs Sorted Set:Set无序,Sorted Set按分数有序
- 使用Set的场景:标签系统、好友关系、去重、抽奖、搜索过滤