news 2026/4/23 14:05:50

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/23 13:52:29

测试文章标题02

测试文章内容这是一篇测试文章

作者头像 李华
网站建设 2026/4/18 7:10:18

3步搞定Editly Docker部署:告别复杂配置的视频编辑新体验

3步搞定Editly Docker部署:告别复杂配置的视频编辑新体验 【免费下载链接】editly Slick, declarative command line video editing & API 项目地址: https://gitcode.com/gh_mirrors/ed/editly 还在为视频编辑工具的繁琐安装而头疼吗?Editly…

作者头像 李华
网站建设 2026/4/23 9:38:17

清华镜像站同步更新|Qwen-Image模型国内高速下载通道开放

清华镜像站同步更新|Qwen-Image模型国内高速下载通道开放 在AIGC浪潮席卷全球的今天,图像生成技术早已不再是实验室里的概念玩具。从电商海报到影视分镜,从品牌设计到教育插图,文生图模型正以前所未有的速度渗透进各行各业。然而…

作者头像 李华
网站建设 2026/4/18 18:46:55

AI Agent的跨模态检索:整合LLM与多媒体数据库

AI Agent的跨模态检索:整合LLM与多媒体数据库关键词:AI Agent、跨模态检索、大语言模型(LLM)、多媒体数据库、信息整合摘要:本文聚焦于AI Agent的跨模态检索,探讨如何将大语言模型(LLM&#xff…

作者头像 李华
网站建设 2026/4/22 4:48:14

AI赋能电商运营新思维

AI赋能电商运营新思维 关键词:AI、电商运营、新思维、数据分析、个性化推荐 摘要:本文深入探讨了AI如何为电商运营带来新思维。通过对AI在电商领域的核心概念、算法原理、数学模型等方面的详细剖析,结合实际项目案例,阐述了AI在电…

作者头像 李华
网站建设 2026/4/23 10:27:54

ionic 单选框详解

ionic 单选框详解 引言 在移动应用开发中,单选框是一种常见的用户界面元素,用于让用户从一组选项中选择一个选项。在Ionic框架中,单选框的创建和使用非常灵活,能够满足不同场景下的需求。本文将详细介绍Ionic单选框的用法、属性和注意事项。 一、单选框的基本用法 在Io…

作者头像 李华