🔗 Redis 集合(Set)

Redis 中的无序不重复元素集合

集合类型概述

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              # 一周内的唯一访问者数量

性能优化建议

集合 vs 其他数据类型

数据类型选择建议:

  • Set vs List:Set不允许重复且无序,List允许重复且有序
  • Set vs Hash:Set存储单一值,Hash存储键值对
  • Set vs Sorted Set:Set无序,Sorted Set按分数有序
  • 使用Set的场景:标签系统、好友关系、去重、抽奖、搜索过滤