news 2026/4/17 2:06:12

Redis Set类型完全指南:无序集合的原理与应用

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
Redis Set类型完全指南:无序集合的原理与应用

引言

Redis的Set(集合)类型是一个无序的、元素不重复的数据结构,它基于哈希表实现,类似于C++中的unordered_set。Set类型在Redis中提供了高效的集合运算能力,特别适合处理需要去重、求交并差集的场景。本篇博客将深入探讨Redis Set的底层原理、核心命令和多种实用场景。

一、Redis Set核心特性

1.1 基本特性

Redis Set
特点
无序存储
元素唯一
高效集合运算
不保证插入顺序
不保证排序顺序
自动去重
插入重复元素返回0
交集sinter
并集sunion
差集sdiff

1.2 与List的对比

特性SetList
顺序性无序有序(插入顺序)
重复性不允许重复允许重复
访问方式不支持下标访问支持下标访问
底层实现哈希表、intsetQuickList
主要用途去重、集合运算队列、栈、时间线

二、Redis Set核心命令详解

2.1 基本操作命令

SADD - 添加元素
# 语法 SADD key member [member ...] # 示例 SADD tags:user:1001 "tech" "music" "sports" # 返回:3(成功添加的元素个数) # 添加重复元素 SADD tags:user:1001 "tech" # 返回:0(元素已存在)
SMEMBERS - 获取所有元素
# 语法 SMEMBERS key # 示例 SMEMBERS tags:user:1001 # 可能返回:"tech", "music", "sports"(顺序不确定) # ⚠️ 警告:时间复杂度O(N),大集合需谨慎使用
SISMEMBER - 检查元素存在
# 语法 SISMEMBER key member # 示例 SISMEMBER tags:user:1001 "tech" # 返回:1(存在) SISMEMBER tags:user:1001 "art" # 返回:0(不存在)
SCARD - 获取元素个数
# 语法 SCARD key # 示例 SADD tags:user:1001 "tech" "music" "sports" SCARD tags:user:1001 # 返回:3 # ⚠️ 时间复杂度:O(1)

2.2 删除与移动操作

SPOP - 随机删除并返回
# 语法 SPOP key [count] # 示例 SADD lottery "user1" "user2" "user3" "user4" "user5" SPOP lottery 2 # 随机删除并返回2个元素 # 可能返回:"user3", "user1"
SREM - 删除指定元素
# 语法 SREM key member [member ...] # 示例 SADD tags:user:1001 "tech" "music" "sports" "art" SREM tags:user:1001 "art" "music" # 删除两个元素 # 返回:2(成功删除的个数)
SMOVE - 移动元素
# 语法 SMOVE source destination member # 示例 SADD blacklist "user:1001" "user:1002" SADD whitelist "user:1003" # 将user:1001从黑名单移到白名单 SMOVE blacklist whitelist "user:1001" # 返回:1(移动成功)

2.3 随机操作

SRANDMEMBER - 随机获取元素
# 语法 SRANDMEMBER key [count] # 示例 SADD colors "red" "green" "blue" "yellow" "purple" # 获取1个随机元素 SRANDMEMBER colors # 可能返回:"green" # 获取3个随机元素(可能重复) SRANDMEMBER colors 3 # 获取3个不重复的随机元素(负数count) SRANDMEMBER colors -3

三、集合运算命令

3.1 交集运算

Set A: 1,2,3,4
交集运算
Set B: 3,4,5,6
结果: 3,4
SINTER - 计算交集
# 语法 SINTER key [key ...] # 示例:共同好友 SADD friends:user1 "user2" "user3" "user4" "user5" SADD friends:user2 "user1" "user3" "user6" "user7" # 计算user1和user2的共同好友 SINTER friends:user1 friends:user2 # 返回:"user3"
SINTERSTORE - 计算并存储交集
# 语法 SINTERSTORE destination key [key ...] # 示例:存储共同好友 SINTERSTORE common:user1:user2 friends:user1 friends:user2 # 返回:1(交集元素个数) SMEMBERS common:user1:user2 # 返回:"user3"

3.2 并集运算

Set A: 1,2,3,4
并集运算
Set B: 3,4,5,6
结果: 1,2,3,4,5,6
SUNION - 计算并集
# 语法 SUNION key [key ...] # 示例:合并标签 SADD tags:article1 "redis" "database" "nosql" SADD tags:article2 "redis" "cache" "performance" # 合并两篇文章的所有标签 SUNION tags:article1 tags:article2 # 返回:"redis", "database", "nosql", "cache", "performance"
SUNIONSTORE - 计算并存储并集
# 语法 SUNIONSTORE destination key [key ...] # 示例:创建标签池 SUNIONSTORE all:tags tags:article1 tags:article2 SCARD all:tags # 返回:5

3.3 差集运算

Set A: 1,2,3,4
A - B
Set B: 3,4,5,6
结果: 1,2
Set B: 3,4,5,6
B - A
Set A: 1,2,3,4
结果: 5,6
SDIFF - 计算差集
# 语法 SDIFF key [key ...] # 示例:个性化推荐 SADD user:1001:viewed "movie1" "movie2" "movie3" "movie4" SADD all:movies "movie1" "movie2" "movie3" "movie4" "movie5" "movie6" # 推荐用户没看过的电影 SDIFF all:movies user:1001:viewed # 返回:"movie5", "movie6"
SDIFFSTORE - 计算并存储差集
# 语法 SDIFFSTORE destination key [key ...] # 示例:创建推荐列表 SDIFFSTORE recommendations:user:1001 all:movies user:1001:viewed SCARD recommendations:user:1001 # 返回:2

四、Redis Set底层实现

4.1 编码方式

Redis Set使用两种编码方式,根据数据特性自动选择:

IntSet(整数集合)
# 当集合满足以下条件时使用IntSet: # 1. 所有元素都是整数 # 2. 元素数量较少(默认512个) # 3. 整数在64位有符号范围内 # 示例:使用IntSet SADD small:numbers 1 2 3 4 5 OBJECT ENCODING small:numbers # 返回:"intset"
HashTable(哈希表)
# 当不满足IntSet条件时使用HashTable # 示例:使用HashTable SADD large:set "string1" "string2" 100 # 包含非整数 OBJECT ENCODING large:set # 返回:"hashtable"

4.2 内存优化配置

# Redis配置文件中Set相关参数 set-max-intset-entries 512 # IntSet最大元素数量 # 当元素数量超过此值或包含非整数时,转换为HashTable

五、Redis Set应用场景

5.1 用户标签系统

用户标签存储
标签: tech,music,sports
标签: tech,art,travel
标签: music,sports,food
标签集合
用户1001
标签集合
用户1002
标签集合
用户1003
基于标签的推荐
计算交集找共同兴趣
计算差集找互补兴趣
计算并集找热门标签

实现代码

# 为用户添加标签 SADD user:1001:tags "tech" "programming" "music" "basketball" SADD user:1002:tags "tech" "music" "travel" "photography" SADD user:1003:tags "music" "sports" "food" "travel" # 1. 找共同兴趣好友(交集) SINTER user:1001:tags user:1002:tags # 返回:"tech", "music" → 推荐user1002给user1001 # 2. 找可能感兴趣的新标签(差集) SDIFF user:1002:tags user:1001:tags # 返回:"travel", "photography" → 推荐给user1001 # 3. 热门标签统计(并集) SUNIONSTORE hot:tags user:1001:tags user:1002:tags user:1003:tags

5.2 共同好友系统

用户1002的好友
用户1001的好友
SINTER
SINTER
friends:user:1002
Set
元素: user:1001, user:1003, user:1005
friends:user:1001
Set
元素: user:1002, user:1003, user:1004
交集运算
common:user:1001:user:1002
结果Set
共同好友: user:1003
推荐系统
推荐逻辑:
1. 共同好友越多,推荐权重越高
2. 二度人脉推荐
3. 兴趣相似度匹配
# 存储好友关系 SADD friends:user:1001 "user:1002" "user:1003" "user:1004" "user:1005" SADD friends:user:1002 "user:1001" "user:1003" "user:1006" "user:1007" # 计算共同好友 SINTER friends:user:1001 friends:user:1002 # 返回:"user:1003" → 有1个共同好友 # 存储共同好友结果 SINTERSTORE common:user:1001:user:1002 friends:user:1001 friends:user:1002 SCARD common:user:1001:user:1002 # 返回:1 # 好友推荐:用户可能认识的人 # user:1001的朋友中,不是user:1002朋友的人 SDIFF friends:user:1001 friends:user:1002 # 返回:"user:1002", "user:1004", "user:1005" # 去掉user:1002(自己),推荐user:1004和user:1005给user:1002

5.3 UV统计(独立访客)

Redis Set 存储层
访问记录层
SADD
SADD
SADD
SADD
SCARD
SUNIONSTORE
SUNIONSTORE
SUNIONSTORE
SCARD
uv:daily:2024-01-15
uv:daily:2024-01-16
uv:daily:2024-01-17
uv:weekly:2024-02
uv:monthly:2024-01
访问请求1
user:1001
访问请求2
user:1002
访问请求3
user:1001
访问请求4
user:1003
当日UV: 3
(user:1001只计1次)
周UV: 去重统计
# 每日UV统计方案 # 1. 记录每日访问用户 SADD uv:2024-01-15 "user:1001" "user:1002" "user:1003" "user:1001" # user:1001重复访问,但只记录一次 # 2. 获取当日UV SCARD uv:2024-01-15 # 返回:3 # 3. 每周UV统计(合并7天数据) SUNIONSTORE uv:week:2024-02 "uv:2024-01-15" "uv:2024-01-16" "uv:2024-01-17" SCARD uv:week:2024-02 # 返回:去重后的总UV # 4. 按月统计 SUNIONSTORE uv:month:2024-01 "uv:2024-01-*" # 需要收集所有key

六、性能优化与最佳实践

6.1 大集合处理策略

# 问题:SMEMBERS处理大集合会阻塞 # 解决方案1:使用SSCAN分批获取 SSCAN large:set 0 COUNT 100 # 分批获取,每次100个 # 解决方案2:拆分为多个小集合 # 按前缀或哈希分片 SADD set:part:1 "item1" "item2" SADD set:part:2 "item3" "item4" # 需要时合并查询

6.2 集合运算性能优化

# 1. 使用*STORE命令减少网络传输 # 不佳:客户端计算 SINTER set1 set2 set3 # 返回大量数据到客户端 # 优化:服务器端存储 SINTERSTORE result set1 set2 set3 # 结果存在Redis中 SMEMBERS result # 需要时再获取 # 2. 预估集合大小 SCARD set1 # O(1)操作,先了解数据规模 SCARD set2 # 3. 合理排序集合参数 # 差集不满足交换律,小集合在前更高效 # set1有10个元素,set2有1000个元素 SDIFF set1 set2 # 更高效 SDIFF set2 set1 # 较低效

七、总结

Redis Set是一个功能强大且高效的数据结构,特别适合处理需要去重和集合运算的场景:

核心优势:

  1. 高效去重:自动保证元素唯一性
  2. 快速查询:O(1)时间复杂度的存在性检查
  3. 丰富运算:支持交、并、差集计算
  4. 内存优化:内部实现IntSet或HashTable编码

适用场景总结:

  • 用户标签系统:基于兴趣的推荐和分组
  • 社交关系:共同好友、好友推荐
  • 统计分析:UV统计、独立计数
  • 内容筛选:多条件过滤、去重
  • 随机选择:抽奖、随机推荐
  • 访问控制:黑白名单管理

最佳实践建议:

  1. 避免大集合:使用SSCAN代替SMEMBERS
  2. 合理使用编码:尽量使用整数和小集合以启用IntSet
  3. 优化集合运算:小集合在前,使用*STORE命令
  4. 及时清理数据:设置合理的过期时间
  5. 监控性能:定期检查大Key和慢查询

掌握Redis Set的特性和应用场景,能够在实际项目中构建更高效、更灵活的数据处理系统。无论是社交应用、电商系统还是数据分析平台,Set都能发挥重要作用。

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/4/16 3:00:38

【EVE-NG镜像制作系列教程】29、Cisco Prime Infra

推荐阅读: 1、EVE-NG 2TB全网最新最全镜像下载地址(保持更新): https://www.emulatedlab.com/thread-939-1-1.html 2、EVE-NG 2025全网最新最全资源大全(保持更新): https://www.emulatedlab.co…

作者头像 李华
网站建设 2026/4/16 9:25:30

Windows系统性能革命:OpenSpeedy加速工具全面解析

Windows系统性能革命:OpenSpeedy加速工具全面解析 【免费下载链接】OpenSpeedy 项目地址: https://gitcode.com/gh_mirrors/op/OpenSpeedy 你是否经常遇到电脑运行卡顿、程序响应缓慢的问题?在当今快节奏的数字时代,系统性能直接影响…

作者头像 李华
网站建设 2026/4/16 18:13:25

MySQL 处理重复数据

MySQL 处理重复数据 引言 在数据库管理中,数据重复是一个常见的问题。重复数据不仅浪费存储空间,还可能导致数据分析的偏差和错误。MySQL作为一种流行的关系型数据库管理系统,提供了多种方法来处理和消除重复数据。本文将详细介绍MySQL处理重复数据的方法,包括查找重复数…

作者头像 李华
网站建设 2026/4/16 13:43:15

10 个专科生毕业答辩PPT模板,AI格式优化工具推荐

10 个专科生毕业答辩PPT模板,AI格式优化工具推荐 时间紧、任务重,论文写作成了“硬骨头” 对于专科生来说,毕业答辩不仅是学习生涯的终点,更是迈向职场的第一道门槛。而在这条路上,最让人头疼的莫过于撰写毕业论文和制…

作者头像 李华
网站建设 2026/4/16 10:56:51

NPM安装前端界面控制Stable Diffusion 3.5 FP8?Node.js集成方案揭秘

Node.js 集成 Stable Diffusion 3.5 FP8:前端如何驱动本地高性能 AI 在生成式AI迅速“飞入寻常百姓家”的今天,一个看似矛盾的趋势正在浮现:我们既渴望更强大的模型,又希望它能在自己的笔记本上流畅运行。Stable Diffusion 3.5 的…

作者头像 李华
网站建设 2026/4/16 10:55:38

线上充值平台如何实现自动开票?四步落地法,告别人工开票痛点

“充值 1 分钟,开票等半天”—— 这是很多互联网平台、会员制服务、电商平台的共同困扰:线上充值订单源源不断,财务团队却要陷入逐笔核对、手动录入、反复修改的低效循环。人工开票不仅占用大量人力成本,还容易因数据误差、开票延…

作者头像 李华