Redis集合
集合(Set)是无序、不重复的字符串集合,支持丰富的集合运算,适合标签、好友关系等场景。
结构概述
基本特点
Bash
- 无序字符串集合
- 元素不重复
- 支持集合运算(交、并、差)
- 单个集合最多2^32-1个元素
与List对比
Bash
List:有序、可重复、两端操作
Set:无序、不重复、集合运算
内部编码
intset编码
Bash
触发条件:
- 所有元素都是整数
- 元素数量 ≤ set-max-intset-entries(默认512)
特点:
- 紧凑连续内存
- 有序存储整数
- 查找O(logN)(二分查找)
- 内存效率极高
hashtable编码
Bash
触发条件:
- 包含非整数元素
- 或元素数量超过512
特点:
- 哈希表结构
- 查找O(1)
- 内存占用较大
- 无序存储
查看编码
Bash
SADD myset 1 2 3
OBJECT ENCODING myset
# 返回: "intset"
SADD myset "a"
OBJECT ENCODING myset
# 返回: "hashtable"(转为hashtable)
编码转换
intset转hashtable
Bash
# 条件1:添加非整数
SADD intset:demo 1 2 3
OBJECT ENCODING intset:demo # "intset"
SADD intset:demo "string"
OBJECT ENCODING intset:demo # "hashtable"
# 条件2:超过512个整数元素
for i in {1..513}; do
SADD large:set $i
done
OBJECT ENCODING large:set # "hashtable"
intset一旦转为hashtable,不可逆回intset。
应用场景
1. 标签系统
Bash
# 用户标签
SADD user:1000:tags "tech" "redis" "nosql"
# 文章标签
SADD article:500:tags "redis" "database" "cache"
# 查找标签下的文章
SADD tag:redis:articles "article:500"
# 查看用户标签
SMEMBERS user:1000:tags
2. 共同好友
Bash
# 用户好友列表
SADD user:1000:friends "user:1001" "user:1002" "user:1003"
SADD user:1001:friends "user:1002" "user:1004"
# 共同好友
SINTER user:1000:friends user:1001:friends
# 返回: "user:1002"
3. 可能认识的人
Bash
# 用户A的朋友
SADD user:A:friends "B" "C" "D"
# 用户B的朋友
SADD user:B:friends "A" "C" "E"
# 推荐好友:B的朋友中不是A朋友的
SDIFF user:B:friends user:A:friends
# 返回: "E"(A可能认识E)
4. 抽奖系统
Bash
# 参与用户
SADD lottery:users "user:1" "user:2" "user:3" "user:4" "user:5"
# 随机抽取获奖者(移除)
SPOP lottery:users
# 返回随机一个用户
# 随机抽取不移除
SRANDMEMBER lottery:users 2
# 随机返回2个用户(不移除)
5. 点赞/收藏
Bash
# 文章点赞用户
SADD article:500:likes "user:1000"
# 检查是否点赞
SISMEMBER article:500:likes "user:1000"
# 返回: 1
# 取消点赞
SREM article:500:likes "user:1000"
# 点赞数
SCARD article:500:likes
6. 唯一性检查
Bash
# 已注册邮箱
SADD emails:registered "alice@example.com" "bob@example.com"
# 检查邮箱是否已注册
SISMEMBER emails:registered "alice@example.com"
# 返回: 1(已注册)
集合运算
交集SINTER
Bash
# 多个集合的共同元素
SINTER set1 set2 set3
# 存储交集结果
SINTERSTORE result set1 set2
# 应用:共同好友、共同关注
并集SUNION
text
# 多个集合的所有元素
SUNION set1 set2
# 存储并集结果
SUNIONSTORE result set1 set2
# 应用:合并标签、合并好友
差集SDIFF
text
# 第一个集合相对于其他集合的差集
SDIFF set1 set2 set3
# 在set1但不在set2和set3的元素
# 存储差集结果
SDIFFSTORE result set1 set2
# 应用:推荐好友、补集
操作特点
O(1)操作
text
SADD:添加元素
SREM:删除元素
SISMEMBER:检查存在
SCARD:元素数量
SPOP:随机弹出
O(N)操作
text
SMEMBERS:获取全部元素
SINTER/SUNION/SDIFF:集合运算
# N为元素数量或集合大小
性能建议
大集合遍历
text
# 避免SMEMBERS获取大量元素
# 使用SSCAN分批遍历
SSCAN myset 0 COUNT 100
集合运算优化
text
- 小集合优先:SINTER从小集合开始
- 结果存储:使用STORE命令避免传输
- 分批处理:大数据集分批运算
控制集合大小
text
- 合理设计集合元素
- 及时清理无用元素
- 避免单个集合过大
注意事项
元素唯一性
text
# 重复添加返回0
SADD myset "a"
SADD myset "a"
# 返回: 0(已存在)
编码转换影响
text
intset编码高效但只支持整数
添加非整数会转为hashtable
转换后内存占用增加
无序性
text
SMEMBERS返回顺序不确定
不依赖元素顺序
排序需求用ZSet
编码对比
| 编码 | 条件 | 内存效率 | 查找效率 |
|---|---|---|---|
| intset | 全整数且≤512 | 极高 | O(logN) |
| hashtable | 非整数或>512 | 中 | O(1) |
与其他类型对比
| 特性 | Set | List | ZSet |
|---|---|---|---|
| 顺序 | 无序 | 有序 | 按分数排序 |
| 重复 | 不允许 | 允许 | 不允许 |
| 索引 | 不支持 | 支持 | 按分数 |
| 运算 | 交/并/差 | 无 | 无 |
要点总结
- 集合是无序不重复的字符串集合
- intset编码适合纯整数小集合(≤512),内存高效
- hashtable编码适合非整数或大集合,O(1)查找
- 应用场景:标签、好友关系、抽奖、点赞、唯一检查
- SINTER交集、SUNION并集、SDIFF差集
- 大集合用SSCAN遍历,避免SMEMBERS阻塞
- intset添加非整数会转为hashtable,不可逆
- 需要有序或排序场景使用ZSet而非Set
📝 发现内容有误?点击此处直接编辑