<返回目录     Powered by claud/xia兄

第5课: 集合操作

Set数据结构与集合运算

一、Set集合简介

Redis的Set是一个无序的字符串集合,集合中的元素是唯一的,不允许重复。Set提供了丰富的集合运算功能,如交集、并集、差集等,非常适合用于标签系统、好友关系、共同关注等场景。

Set的特点

二、基本操作命令

1. SADD - 添加元素

向集合中添加一个或多个成员,如果成员已存在则忽略。

# 添加单个元素
SADD myset "apple"
# 返回: (integer) 1

# 添加多个元素
SADD myset "banana" "orange" "grape"
# 返回: (integer) 3

# 添加已存在的元素(会被忽略)
SADD myset "apple"
# 返回: (integer) 0

# 实际应用:用户标签系统
SADD user:1001:tags "python" "golang" "redis"
SADD user:1002:tags "java" "mysql" "redis"

2. SMEMBERS - 获取所有成员

返回集合中的所有成员。

# 获取集合所有成员
SMEMBERS myset
# 返回:
# 1) "grape"
# 2) "orange"
# 3) "banana"
# 4) "apple"

# 查看用户标签
SMEMBERS user:1001:tags
# 返回:
# 1) "python"
# 2) "golang"
# 3) "redis"

3. SISMEMBER - 判断成员是否存在

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

# 判断元素是否存在
SISMEMBER myset "apple"
# 返回: (integer) 1  # 1表示存在

SISMEMBER myset "watermelon"
# 返回: (integer) 0  # 0表示不存在

# 实际应用:检查用户是否有某个标签
SISMEMBER user:1001:tags "python"
# 返回: (integer) 1

4. SCARD - 获取集合元素数量

返回集合中元素的数量。

# 获取集合大小
SCARD myset
# 返回: (integer) 4

# 统计用户标签数量
SCARD user:1001:tags
# 返回: (integer) 3

5. SREM - 删除元素

移除集合中一个或多个成员。

# 删除单个元素
SREM myset "apple"
# 返回: (integer) 1

# 删除多个元素
SREM myset "banana" "grape"
# 返回: (integer) 2

# 删除不存在的元素
SREM myset "watermelon"
# 返回: (integer) 0

# 实际应用:移除用户标签
SREM user:1001:tags "golang"

6. SPOP - 随机移除元素

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

# 随机移除一个元素
SPOP myset
# 返回: "orange"

# 随机移除多个元素
SPOP myset 2
# 返回:
# 1) "grape"
# 2) "banana"

# 实际应用:抽奖系统
SADD lottery:pool "user1" "user2" "user3" "user4" "user5"
SPOP lottery:pool 3  # 随机抽取3个中奖用户

7. SRANDMEMBER - 随机获取元素

随机返回集合中的一个或多个元素,但不移除。

# 随机获取一个元素
SRANDMEMBER myset
# 返回: "apple"

# 随机获取多个元素(不重复)
SRANDMEMBER myset 2
# 返回:
# 1) "banana"
# 2) "orange"

# 随机获取多个元素(可重复,使用负数)
SRANDMEMBER myset -5
# 返回:
# 1) "apple"
# 2) "apple"
# 3) "banana"
# 4) "orange"
# 5) "banana"

三、集合运算操作

1. SINTER - 交集运算

返回多个集合的交集(共同元素)。

# 创建测试数据
SADD set1 "a" "b" "c" "d"
SADD set2 "c" "d" "e" "f"
SADD set3 "d" "e" "f" "g"

# 计算两个集合的交集
SINTER set1 set2
# 返回:
# 1) "c"
# 2) "d"

# 计算三个集合的交集
SINTER set1 set2 set3
# 返回:
# 1) "d"

# 实际应用:查找共同好友
SADD user:1001:friends "user2" "user3" "user4" "user5"
SADD user:1002:friends "user3" "user4" "user6" "user7"
SINTER user:1001:friends user:1002:friends
# 返回共同好友: user3, user4

2. SINTERSTORE - 交集存储

计算交集并将结果存储到新集合中。

# 计算交集并存储
SINTERSTORE result set1 set2
# 返回: (integer) 2  # 交集元素数量

# 查看结果
SMEMBERS result
# 返回:
# 1) "c"
# 2) "d"

# 实际应用:生成共同兴趣标签
SINTERSTORE user:common:tags user:1001:tags user:1002:tags

3. 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"

# 实际应用:合并多个用户的标签
SUNION user:1001:tags user:1002:tags user:1003:tags

4. SUNIONSTORE - 并集存储

计算并集并将结果存储到新集合中。

# 计算并集并存储
SUNIONSTORE result set1 set2 set3
# 返回: (integer) 7  # 并集元素数量

# 查看结果
SMEMBERS result

5. SDIFF - 差集运算

返回第一个集合与其他集合的差集(在第一个集合中但不在其他集合中的元素)。

# 计算差集(set1中有但set2中没有的元素)
SDIFF set1 set2
# 返回:
# 1) "a"
# 2) "b"

# 计算差集(set2中有但set1中没有的元素)
SDIFF set2 set1
# 返回:
# 1) "e"
# 2) "f"

# 多个集合的差集
SDIFF set1 set2 set3
# 返回:
# 1) "a"
# 2) "b"

# 实际应用:查找独有好友
SDIFF user:1001:friends user:1002:friends
# 返回user1001独有的好友

6. SDIFFSTORE - 差集存储

计算差集并将结果存储到新集合中。

# 计算差集并存储
SDIFFSTORE result set1 set2
# 返回: (integer) 2

# 查看结果
SMEMBERS result
# 返回:
# 1) "a"
# 2) "b"

四、实际应用场景

1. 标签系统

# 为文章添加标签
SADD article:1001:tags "redis" "nosql" "database" "cache"
SADD article:1002:tags "python" "redis" "programming"

# 查找同时包含redis和python标签的文章
SINTER article:1001:tags article:1002:tags

# 查找所有标签
SUNION article:1001:tags article:1002:tags

2. 社交关系

# 用户关注关系
SADD user:1001:following "user2" "user3" "user4"
SADD user:1002:following "user3" "user4" "user5"

# 查找共同关注
SINTER user:1001:following user:1002:following

# 查找user1001关注但user1002没关注的人
SDIFF user:1001:following user:1002:following

# 推荐关注(user1002关注但user1001没关注的人)
SDIFF user:1002:following user:1001:following

3. 点赞/收藏系统

# 用户点赞文章
SADD article:1001:likes "user1" "user2" "user3"
SADD article:1002:likes "user2" "user3" "user4"

# 检查用户是否点赞
SISMEMBER article:1001:likes "user1"

# 获取点赞数
SCARD article:1001:likes

# 取消点赞
SREM article:1001:likes "user1"

# 查找同时点赞两篇文章的用户
SINTER article:1001:likes article:1002:likes

4. 抽奖系统

# 添加参与抽奖的用户
SADD lottery:2024:pool "user1" "user2" "user3" "user4" "user5"

# 抽取1个一等奖
SPOP lottery:2024:pool 1

# 抽取2个二等奖
SPOP lottery:2024:pool 2

# 查看剩余参与者
SMEMBERS lottery:2024:pool

5. 在线用户统计

# 用户上线
SADD online:users "user1001"
SADD online:users "user1002"

# 用户下线
SREM online:users "user1001"

# 获取在线用户数
SCARD online:users

# 检查用户是否在线
SISMEMBER online:users "user1002"

五、常用命令对照表

命令 功能 时间复杂度
SADD 添加元素 O(N)
SREM 删除元素 O(N)
SISMEMBER 判断元素是否存在 O(1)
SMEMBERS 获取所有成员 O(N)
SCARD 获取集合大小 O(1)
SPOP 随机移除元素 O(1)
SRANDMEMBER 随机获取元素 O(N)
SINTER 交集运算 O(N*M)
SUNION 并集运算 O(N)
SDIFF 差集运算 O(N)
性能优化建议:

六、实践练习

练习任务:
  1. 创建三个用户的标签集合,每个用户至少5个标签
  2. 使用SINTER查找三个用户的共同标签
  3. 使用SUNION获取所有不重复的标签
  4. 使用SDIFF找出第一个用户独有的标签
  5. 实现一个简单的文章推荐系统:根据用户标签推荐相关文章
  6. 实现一个抽奖系统:从100个用户中随机抽取10个中奖者
  7. 实现一个在线用户统计功能:记录用户上线/下线,统计在线人数
  8. 使用Set实现一个简单的好友推荐功能(推荐共同好友的好友)

七、总结

Redis的Set数据结构提供了强大的集合运算功能,非常适合处理标签、关系、去重等场景。掌握Set的各种操作命令和集合运算,可以高效地解决很多实际业务问题。在使用时要注意性能问题,特别是在处理大集合时,要选择合适的命令和策略。