Redis命令-Set命令

一、前言:Set ------ Redis 中的"数学集合"

在 Redis 的五大数据类型中,Set(集合) 是最贴近数学概念的一种:

  • ✅ 元素唯一(自动去重)
  • 无序(不保证插入顺序)
  • ✅ 支持交集、并集、差集等集合运算

它不仅是去重工具,更是实现:

  • 共同好友推荐
  • 用户标签系统
  • 抽奖去重
  • 权限管理

的核心数据结构!

本文将带你:

✅ 掌握 Set 的核心命令

✅ 理解其底层实现(intset / hashtable)

✅ 结合真实业务场景

✅ 避开常见使用误区


二、Set 类型基本特性

  • 元素唯一性:重复添加无效
  • 无序性SMEMBERS 返回顺序不可预测
  • 支持集合运算:交(SINTER)、并(SUNION)、差(SDIFF)
  • 底层编码
    • intset:所有元素为整数且数量少(默认 ≤ 512)
    • hashtable:包含字符串或元素较多时
  • 时间复杂度SADD / SISMEMBER / SREM 均为 O(1)

三、核心命令详解(附实战示例)

1. SADD key member [member ...] ------ 添加元素

bash 复制代码
# 添加用户标签
SADD user:1001:tags "科技" "篮球" "电影"

# 重复添加无效
SADD user:1001:tags "科技"
# 返回 0(未新增)

✅ 返回值:成功添加的元素个数


2. SMEMBERS key ------ 获取所有元素

bash 复制代码
SMEMBERS user:1001:tags
# 返回 1) "电影" 2) "篮球" 3) "科技" (顺序随机)

⚠️ 慎用 :当 Set 很大时(如百万级),会阻塞 Redis!

✅ 替代方案:用 SSCAN 分批遍历


3. SISMEMBER key member ------ 判断元素是否存在

bash 复制代码
SISMEMBER user:1001:tags "足球"
# 返回 0(不存在)

SISMEMBER user:1001:tags "篮球"
# 返回 1(存在)

典型用途

  • 判断用户是否已参与活动
  • 检查权限是否包含某角色

4. SREM key member [member ...] ------ 删除元素

bash 复制代码
# 移除标签
SREM user:1001:tags "电影" "游戏"

💡 不会删除整个 Key,除非所有元素都被移除


5. SCARD key ------ 获取集合大小

bash 复制代码
SCARD user:1001:tags
# 返回 3

✅ O(1) 操作,高效可靠


6. SRANDMEMBER key [count] ------ 随机获取元素

bash 复制代码
# 随机返回 1 个标签
SRANDMEMBER user:1001:tags

# 随机返回 2 个不重复标签
SRANDMEMBER user:1001:tags 2

# 随机返回 3 个可重复标签(带负数)
SRANDMEMBER user:1001:tags -3

🎯 应用场景

  • 抽奖系统(去重随机)
  • 推荐系统冷启动(随机曝光)

7. 集合运算命令(多 Key 操作)

命令 作用 示例
SINTER key1 key2 ... 交集 共同好友
SUNION key1 key2 ... 并集 合并标签
SDIFF key1 key2 差集(key1 - key2) A 关注但 B 未关注的人
bash 复制代码
# 用户 A 和 B 的共同兴趣
SINTER user:1001:tags user:1002:tags
# 返回 1) "科技" 2) "篮球"

# A 有但 B 没有的标签
SDIFF user:1001:tags user:1002:tags

⚡ 所有集合运算均为原子操作,并发安全!


四、Set 的典型应用场景

场景 1:用户标签系统

bash 复制代码
SADD user:1001:tags "男性" "25-30岁" "一线城市" "程序员"
SADD user:1002:tags "女性" "20-25岁" "二线城市" "设计师"

# 精准推送:找"程序员"标签用户
SISMEMBER user:1001:tags "程序员" → true

✅ 优势:标签增删快,查询 O(1)


场景 2:共同好友/关注推荐

bash 复制代码
# 用户关注列表
SADD follows:1001 2001 2002 2003
SADD follows:1002 2002 2003 2004

# 共同关注
SINTER follows:1001 follows:1002
# 返回 2002, 2003

💡 社交网络的核心功能之一


场景 3:抽奖去重

bash 复制代码
# 用户参与抽奖
SADD lottery:20241103 user_1001
SADD lottery:20241103 user_1002

# 防止重复参与
SISMEMBER lottery:20241103 user_1001 → true(已参与)

# 随机抽取 3 名幸运用户
SRANDMEMBER lottery:20241103 3

🔒 天然去重,无需额外校验


场景 4:IP 黑名单/白名单

bash 复制代码
SADD ip:blacklist "192.168.1.100" "10.0.0.5"

# 请求时检查
SISMEMBER ip:blacklist $client_ip

✅ 比数据库查询快几个数量级


五、Set vs List 对比

特性 Set List
元素唯一 ✅ 自动去重 ❌ 允许重复
有序性 ❌ 无序 ✅ 有序
随机访问 ❌ 不支持 ✅ 支持(但慢)
集合运算 ✅ 交/并/差 ❌ 不支持
适用场景 去重、关系计算 队列、最新列表

📌 选型建议

  • 需要去重或做关系计算 → Set
  • 需要保持顺序或实现队列 → List

六、常见误区与最佳实践

❌ 误区 1:用 SMEMBERS 遍历大 Set

风险 :O(N) 操作,导致 Redis 卡顿
替代 :使用 SSCAN 分批读取

bash 复制代码
SSCAN user:big_set 0 MATCH * COUNT 100

❌ 误区 2:存储超大 Set(如千万级用户 ID)

问题 :单 Key 内存占用高,影响性能
建议 :分片存储(如 user:tag:tech:shard1, shard2...)

✅ 最佳实践:

  • Key 命名规范业务:实体:属性(如 user:1001:tags
  • 避免 Big Set:单 Set 元素 ≤ 10,000
  • 集合运算前评估数据量:两个百万级 Set 求交集可能耗时秒级
  • SISMEMBER 代替 SMEMBERS + 遍历:判断存在性更高效

七、底层实现:intset 与 hashtable 的自动切换

Redis 根据以下条件自动选择编码:

  • 所有元素为整数
  • 元素数量 ≤ set-max-intset-entries(默认 512)

满足则用 intset (内存紧凑,整数排序存储),否则用 hashtable

💡 可通过 OBJECT ENCODING myset 查看当前编码。


八、结语

感谢您的阅读!如果你有任何疑问或想要分享的经验,请在评论区留言交流!

相关推荐
编程小风筝2 小时前
Spring 框架如何整合Redis缓存中间件?
redis·spring·缓存
Linux-palpitate2 小时前
PostgreSQL(PG)的1主2从集群部署安装
数据库·postgresql
heartbeat..2 小时前
数据库基础知识体系:概念、约束、范式与国产产品
java·数据库·学习笔记·国产数据库
山峰哥3 小时前
数据库工程核心:SQL调优让查询效率飙升的实战密码
网络·汇编·数据库·sql·编辑器
Coder_Boy_4 小时前
基于SpringAI的在线考试系统-DDD业务领域模块设计思路
java·数据库·人工智能·spring boot·ddd
小雪_Snow4 小时前
Windows 安装 MySQL 8.0 教程【安装包方式】
数据库·mysql
无敌的牛4 小时前
MySQL初阶
数据库·mysql
光明顶上的5G5 小时前
本地缓存面试重点
java·缓存·面试
不会C++的雾5 小时前
Linux操作系统(2)
linux·数据库·mysql