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 查看当前编码。


八、结语

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

相关推荐
运维行者_14 小时前
企业无线网络监控的挑战与智能化演进趋势
大数据·运维·服务器·网络·数据库
国强_dev15 小时前
技术探讨:使用 stunnel 加密转发数据库连接时,如何获取客户端真实 IP?
数据库·网络协议·tcp/ip
@insist12315 小时前
系统规划与管理师-信息系统规划核心工作要点解析
数据库·软考·系统规划与管理师·软件水平考试·系统规划与管理工程师
超级数据查看器15 小时前
超级数据查看器 v10.0 发布
java·大数据·数据库·sqlite·安卓
数安3000天15 小时前
增量数据如何自动分类分级,避免目录“过期“?
大数据·数据库
桌面运维家16 小时前
如何用半缓存云桌面将服务器硬盘容量扩展至本地终端?
运维·服务器·缓存
南墙上的石头16 小时前
麒麟 V10 重装人大金仓 V8R6 踩坑实录(含 MySQL 兼容模式)
数据库·mysql
画中有画17 小时前
论向量数据库在项目中的应用
数据库
spider_xcxc18 小时前
Redis 数据库高质量实践指南(一)
运维·数据库·redis·oracle·云计算
l1t18 小时前
在linux和windows中解决duckdb 1.6dev版本输出执行计划报错问题
linux·运维·数据库·windows·duckdb