工业4.0时代,工控一体机如何帮企业实现降本增效?20年从业者深度解析
2026/6/5 23:17:07
Redis的Set(集合)类型是一个无序的、元素不重复的数据结构,它基于哈希表实现,类似于C++中的unordered_set。Set类型在Redis中提供了高效的集合运算能力,特别适合处理需要去重、求交并差集的场景。本篇博客将深入探讨Redis Set的底层原理、核心命令和多种实用场景。
| 特性 | Set | List |
|---|---|---|
| 顺序性 | 无序 | 有序(插入顺序) |
| 重复性 | 不允许重复 | 允许重复 |
| 访问方式 | 不支持下标访问 | 支持下标访问 |
| 底层实现 | 哈希表、intset | QuickList |
| 主要用途 | 去重、集合运算 | 队列、栈、时间线 |
# 语法 SADD key member [member ...] # 示例 SADD tags:user:1001 "tech" "music" "sports" # 返回:3(成功添加的元素个数) # 添加重复元素 SADD tags:user:1001 "tech" # 返回:0(元素已存在)# 语法 SMEMBERS key # 示例 SMEMBERS tags:user:1001 # 可能返回:"tech", "music", "sports"(顺序不确定) # ⚠️ 警告:时间复杂度O(N),大集合需谨慎使用# 语法 SISMEMBER key member # 示例 SISMEMBER tags:user:1001 "tech" # 返回:1(存在) SISMEMBER tags:user:1001 "art" # 返回:0(不存在)# 语法 SCARD key # 示例 SADD tags:user:1001 "tech" "music" "sports" SCARD tags:user:1001 # 返回:3 # ⚠️ 时间复杂度:O(1)# 语法 SPOP key [count] # 示例 SADD lottery "user1" "user2" "user3" "user4" "user5" SPOP lottery 2 # 随机删除并返回2个元素 # 可能返回:"user3", "user1"# 语法 SREM key member [member ...] # 示例 SADD tags:user:1001 "tech" "music" "sports" "art" SREM tags:user:1001 "art" "music" # 删除两个元素 # 返回:2(成功删除的个数)# 语法 SMOVE source destination member # 示例 SADD blacklist "user:1001" "user:1002" SADD whitelist "user:1003" # 将user:1001从黑名单移到白名单 SMOVE blacklist whitelist "user:1001" # 返回:1(移动成功)# 语法 SRANDMEMBER key [count] # 示例 SADD colors "red" "green" "blue" "yellow" "purple" # 获取1个随机元素 SRANDMEMBER colors # 可能返回:"green" # 获取3个随机元素(可能重复) SRANDMEMBER colors 3 # 获取3个不重复的随机元素(负数count) SRANDMEMBER colors -3# 语法 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 destination key [key ...] # 示例:存储共同好友 SINTERSTORE common:user1:user2 friends:user1 friends:user2 # 返回:1(交集元素个数) SMEMBERS common:user1:user2 # 返回:"user3"# 语法 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 destination key [key ...] # 示例:创建标签池 SUNIONSTORE all:tags tags:article1 tags:article2 SCARD all:tags # 返回:5# 语法 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 destination key [key ...] # 示例:创建推荐列表 SDIFFSTORE recommendations:user:1001 all:movies user:1001:viewed SCARD recommendations:user:1001 # 返回:2Redis Set使用两种编码方式,根据数据特性自动选择:
# 当集合满足以下条件时使用IntSet: # 1. 所有元素都是整数 # 2. 元素数量较少(默认512个) # 3. 整数在64位有符号范围内 # 示例:使用IntSet SADD small:numbers 1 2 3 4 5 OBJECT ENCODING small:numbers # 返回:"intset"# 当不满足IntSet条件时使用HashTable # 示例:使用HashTable SADD large:set "string1" "string2" 100 # 包含非整数 OBJECT ENCODING large:set # 返回:"hashtable"# Redis配置文件中Set相关参数 set-max-intset-entries 512 # IntSet最大元素数量 # 当元素数量超过此值或包含非整数时,转换为HashTable实现代码:
# 为用户添加标签 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# 存储好友关系 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# 每日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# 问题:SMEMBERS处理大集合会阻塞 # 解决方案1:使用SSCAN分批获取 SSCAN large:set 0 COUNT 100 # 分批获取,每次100个 # 解决方案2:拆分为多个小集合 # 按前缀或哈希分片 SADD set:part:1 "item1" "item2" SADD set:part:2 "item3" "item4" # 需要时合并查询# 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是一个功能强大且高效的数据结构,特别适合处理需要去重和集合运算的场景:
掌握Redis Set的特性和应用场景,能够在实际项目中构建更高效、更灵活的数据处理系统。无论是社交应用、电商系统还是数据分析平台,Set都能发挥重要作用。