redis set(长文讲解)

更新时间:

💡一则或许对你有用的小广告

欢迎加入小哈的星球 ,你将获得:专属的项目实战 / 1v1 提问 / Java 学习路线 / 学习打卡 / 每月赠书 / 社群讨论

  • 新项目:《从零手撸:仿小红书(微服务架构)》 正在持续爆肝中,基于 Spring Cloud Alibaba + Spring Boot 3.x + JDK 17...点击查看项目介绍 ;
  • 《从零手撸:前后端分离博客项目(全栈开发)》 2 期已完结,演示链接: http://116.62.199.48/ ;

截止目前, 星球 内专栏累计输出 82w+ 字,讲解图 3441+ 张,还在持续爆肝中.. 后续还会上新更多项目,目标是将 Java 领域典型的项目都整一波,如秒杀系统, 在线商城, IM 即时通讯,权限管理,Spring Cloud Alibaba 微服务等等,已有 2900+ 小伙伴加入学习 ,欢迎点击围观

什么是 Redis Set?

Redis Set 是一种无序、不重复的字符串元素集合,类似于数学中的集合概念。它通过哈希表实现,支持快速添加、删除和查询元素,同时提供交集、并集、差集等集合运算功能。对于需要存储唯一值且频繁进行集合操作的场景,Redis Set 是理想的选择。

例如,你可以用 Redis Set 存储网站的独立访客 ID,或者管理标签与文章的关联关系。它的核心特性包括:

  • 元素唯一性:同一个 Set 中不能有重复元素。
  • 无序性:元素存储顺序与添加顺序无关。
  • 高效性:所有操作的时间复杂度均为 O(1) 或 O(N),适合高并发场景。

Redis Set 的基础操作命令

1. 添加元素:SADD

SADD key member [member ...] 命令用于向 Set 中添加一个或多个元素。若元素已存在,则忽略该操作。

示例代码

SADD fruits apple banana orange  
SADD fruits apple mango       # 第二次添加 apple 会被忽略  

2. 查询元素:SISMEMBER

SISMEMBER key member 返回 1 表示存在,0 表示不存在。

示例代码

SISMEMBER fruits banana      # 返回 1  
SISMEMBER fruits grape       # 返回 0  

3. 获取所有元素:SMEMBERS

SMEMBERS key 返回 Set 中的所有元素,结果以列表形式展示。

示例代码

SMEMBERS fruits              # 输出 [apple, banana, orange, mango]  

4. 删除元素:SREM

SREM key member [member ...] 用于删除指定元素。若元素不存在,不会报错。

示例代码

SREM fruits banana           # 删除 banana  
SMEMBERS fruits              # 输出 [apple, orange, mango]  

5. 获取元素数量:SCARD

SCARD key 返回 Set 中元素的总数。

示例代码

SCARD fruits                 # 返回 3  

Redis Set 的集合运算

Redis Set 的强大之处在于支持多种集合运算,这些操作在社交网络、推荐系统等场景中非常实用。

1. 交集运算:SINTER

SINTER key [key ...] 返回多个 Set 的共同元素。

示例场景
假设用户 A 和用户 B 分别收藏了以下电影:

SADD user_a_movies "Inception" "Interstellar" "The Matrix"  
SADD user_b_movies "Inception" "The Dark Knight" "The Matrix"  

通过 SINTER user_a_movies user_b_movies 可以找到两人共同喜欢的电影:

["Inception", "The Matrix"]  

2. 并集运算:SUNION

SUNION key [key ...] 返回多个 Set 的所有元素(去重后)。

示例场景
统计网站 A 和网站 B 的独立访客总数:

SADD website_a_visitors "user1" "user2" "user3"  
SADD website_b_visitors "user2" "user4" "user5"  
SUNION website_a_visitors website_b_visitors    # 输出 ["user1", "user2", "user3", "user4", "user5"]  

3. 差集运算:SDIFF

SDIFF key destination_key [key ...] 返回第一个 Set 中存在但其他 Set 中不存在的元素。

示例场景
找出仅在用户 A 的收藏列表中出现的电影:

SDIFF user_a_movies user_b_movies   # 输出 ["Interstellar"]  

集合运算的存储操作

若希望将运算结果存储到新 Set 中,可以使用带 STORE 后缀的命令:

  • SINTERSTORE:存储交集结果
  • SUNIONSTORE:存储并集结果
  • SDIFFSTORE:存储差集结果

示例代码

SINTERSTORE common_movies user_a_movies user_b_movies  
SMEMBERS common_movies                 # 输出 ["Inception", "The Matrix"]  

Redis Set 的实际应用场景

场景 1:统计独立访客

假设你需要统计某篇文章的独立阅读次数。每次用户访问时,将用户 ID 添加到一个 Set 中:

SADD article_123_views user_id_123  

最终通过 SCARD 获取总访问人数:

SCARD article_123_views    # 返回唯一访问者的数量  

场景 2:实现标签系统

文章与标签的关联可通过 Set 实现。例如,文章 1001 标有 "技术" 和 "编程" 标签:

SADD article_1001_tags "技术" "编程"  

查询所有带有 "编程" 标签的文章,可以通过遍历所有文章的标签 Set,但这可能效率较低。更好的方式是反向索引:

SADD tag_编程_articles "article_1001" "article_2002"  

场景 3:抽奖系统

从大量用户中随机抽取幸运用户时,可以先将所有用户存入一个 Set,然后使用 SRANDMEMBER 随机获取元素:

SADD participants user_1 user_2 ... user_10000  
SRANDMEMBER participants 5     # 随机选取5个用户  

Redis Set 的高级用法

1. 随机元素获取:SRANDMEMBER

SRANDMEMBER key [count] 可以随机返回一个或多个元素,且支持重复获取(通过 REPLACE 参数)。

示例代码

SRANDMEMBER fruits 2          # 返回两个随机元素,如 ["mango", "apple"]  

2. 原子性操作:SPOP

SPOP key [count] 用于随机删除并返回元素,常用于实现分布式锁或任务队列。

示例场景
从任务池中取出待处理的任务:

SADD task_pool "task_1" "task_2" "task_3"  
SPOP task_pool 1               # 返回一个任务并从集合中删除  

3. 有序集合与 Set 的结合

虽然 Set 本身无序,但可以通过 SORTED SET(ZSET)结合分数实现有序存储。例如,记录用户的登录时间:

ZADD last_login_times user_123 1704987600    # 时间戳作为分数  

Redis Set 的性能优化

1. 避免频繁的集合运算

集合运算的时间复杂度为 O(N),当数据量极大时可能影响性能。建议:

  • 对于超大规模数据,分批次处理或使用 Lua 脚本优化
  • 使用 Redis 6.0+ 的 SINTERCARD 直接获取交集元素数量,避免实际计算集合

2. 合理设置过期时间

通过 EXPIREPEXIRE 为 Set 设置过期时间,避免内存浪费。例如:

EXPIRE session_set 3600       # Set 1小时后自动失效  

3. 使用 Pipeline 提升批量操作效率

当需要频繁添加或删除元素时,使用 Pipeline 可减少网络延迟。例如:

MULTI  
  SADD fruits grape  
  SADD fruits kiwi  
EXEC  

常见问题与解决方案

问题 1:元素重复添加后如何处理?

Redis Set 会自动去重,无需额外操作。但若需记录重复次数,可改用 Hash 或 Sorted Set。

问题 2:如何实现 Set 的增量更新?

使用 SUNIONSTORE 将两个 Set 合并到新 Set 中:

SUNIONSTORE new_set set_a set_b  

问题 3:Set 的最大容量是多少?

Redis Set 的理论容量为 2^32-1 元素(约43亿),但实际受限于内存。建议合理规划数据规模。

总结

Redis Set 作为一种轻量级、高性能的集合数据结构,为开发者提供了丰富的操作接口和灵活的使用场景。无论是统计独立用户、实现推荐系统,还是处理复杂的数据关系,Redis Set 都能以简洁的方式解决问题。

通过本文的讲解,读者应能掌握 Set 的基本操作、集合运算、实际应用及优化技巧。在后续实践中,建议结合具体业务需求,探索更多高级功能(如与发布/订阅的结合)或与其他数据类型的组合使用,进一步提升系统性能与扩展性。

(全文约 1800 字)

最新发布