Set数据结构与集合运算
Redis的Set是一个无序的字符串集合,集合中的元素是唯一的,不允许重复。Set提供了丰富的集合运算功能,如交集、并集、差集等,非常适合用于标签系统、好友关系、共同关注等场景。
向集合中添加一个或多个成员,如果成员已存在则忽略。
# 添加单个元素
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"
返回集合中的所有成员。
# 获取集合所有成员
SMEMBERS myset
# 返回:
# 1) "grape"
# 2) "orange"
# 3) "banana"
# 4) "apple"
# 查看用户标签
SMEMBERS user:1001:tags
# 返回:
# 1) "python"
# 2) "golang"
# 3) "redis"
判断元素是否是集合的成员。
# 判断元素是否存在
SISMEMBER myset "apple"
# 返回: (integer) 1 # 1表示存在
SISMEMBER myset "watermelon"
# 返回: (integer) 0 # 0表示不存在
# 实际应用:检查用户是否有某个标签
SISMEMBER user:1001:tags "python"
# 返回: (integer) 1
返回集合中元素的数量。
# 获取集合大小
SCARD myset
# 返回: (integer) 4
# 统计用户标签数量
SCARD user:1001:tags
# 返回: (integer) 3
移除集合中一个或多个成员。
# 删除单个元素
SREM myset "apple"
# 返回: (integer) 1
# 删除多个元素
SREM myset "banana" "grape"
# 返回: (integer) 2
# 删除不存在的元素
SREM myset "watermelon"
# 返回: (integer) 0
# 实际应用:移除用户标签
SREM user:1001:tags "golang"
随机移除并返回集合中的一个或多个元素。
# 随机移除一个元素
SPOP myset
# 返回: "orange"
# 随机移除多个元素
SPOP myset 2
# 返回:
# 1) "grape"
# 2) "banana"
# 实际应用:抽奖系统
SADD lottery:pool "user1" "user2" "user3" "user4" "user5"
SPOP lottery:pool 3 # 随机抽取3个中奖用户
随机返回集合中的一个或多个元素,但不移除。
# 随机获取一个元素
SRANDMEMBER myset
# 返回: "apple"
# 随机获取多个元素(不重复)
SRANDMEMBER myset 2
# 返回:
# 1) "banana"
# 2) "orange"
# 随机获取多个元素(可重复,使用负数)
SRANDMEMBER myset -5
# 返回:
# 1) "apple"
# 2) "apple"
# 3) "banana"
# 4) "orange"
# 5) "banana"
返回多个集合的交集(共同元素)。
# 创建测试数据
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
计算交集并将结果存储到新集合中。
# 计算交集并存储
SINTERSTORE result set1 set2
# 返回: (integer) 2 # 交集元素数量
# 查看结果
SMEMBERS result
# 返回:
# 1) "c"
# 2) "d"
# 实际应用:生成共同兴趣标签
SINTERSTORE user:common:tags user:1001:tags user:1002:tags
返回多个集合的并集(所有不重复元素)。
# 计算两个集合的并集
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
计算并集并将结果存储到新集合中。
# 计算并集并存储
SUNIONSTORE result set1 set2 set3
# 返回: (integer) 7 # 并集元素数量
# 查看结果
SMEMBERS result
返回第一个集合与其他集合的差集(在第一个集合中但不在其他集合中的元素)。
# 计算差集(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独有的好友
计算差集并将结果存储到新集合中。
# 计算差集并存储
SDIFFSTORE result set1 set2
# 返回: (integer) 2
# 查看结果
SMEMBERS result
# 返回:
# 1) "a"
# 2) "b"
# 为文章添加标签
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
# 用户关注关系
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
# 用户点赞文章
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
# 添加参与抽奖的用户
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
# 用户上线
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) |
Redis的Set数据结构提供了强大的集合运算功能,非常适合处理标签、关系、去重等场景。掌握Set的各种操作命令和集合运算,可以高效地解决很多实际业务问题。在使用时要注意性能问题,特别是在处理大集合时,要选择合适的命令和策略。