Redis Set数据类型:从青铜到王者的全方位指南
一、介绍:这货到底是个啥?
Redis的Set是一种无序、唯一 的字符串集合,底层基于哈希表或整数集合实现。它的核心特点就俩字:快 (O(1)时间复杂度)和独 (元素不重复)。你可以把它想象成一个"社交恐惧症患者"------绝不接受重复数据,但能轻松帮你处理交集、并集、差集等社交关系。
底层编码:
- Intset(整数集合):当元素全是整数且数量≤512时,变身"内存抠门精"。
- Hashtable(哈希表):其他情况下,老老实实用哈希表,字典键存元素,值全为NULL(参考Java的HashSet)。
二、用法:Set的十八般武艺
基础操作(单身狗模式)
SADD
:添加元素(重复?不存在的!)SMEMBERS
:查看所有成员(但顺序随机,强迫症慎用)SISMEMBER
:查户口(判断元素是否存在)SPOP
:随机踢人(抽奖神器)。
高阶操作(社交达人模式)
- 交集 (
SINTER
):找共同好友?秒出结果! - 并集 (
SUNION
):合并多个粉丝列表,一键搞定! - 差集 (
SDIFF
):发现"他关注了谁,而你没关注"。
三、案例:Set的职场生存记
1. 社交App的共同好友
刘备的好友集合:SADD user:刘备 赵子龙 张飞 关羽 貂蝉
曹操的好友集合:SADD user:曹操 貂蝉 夏侯惇 典韦
共同好友?一条命令搞定:
bash
SINTERSTORE user:曹刘好友 user:刘备 user:曹操
结果:貂蝉(原来两位大佬都喜欢美女!)。
2. 点赞系统
- 用户A点赞文章:
SADD article:1 uid:A
- 取消点赞:
SREM article:1 uid:A
- 查看谁点了赞:
SMEMBERS article:1
。
3. 抽奖活动
- 参与用户:
SADD lucky_draw user1 user2 user3
- 抽3个不重复的幸运儿:
SPOP lucky_draw 3
- 抽3个可重复的(比如锦鲤转发):
SRANDMEMBER lucky_draw 3
。
四、原理:Set的"内功心法"
1. Intset的升级机制
当插入一个"大整数"(比如65535)导致原有int16数组装不下时,Redis会默默将intset升级为int32或int64,像搬家一样把旧数据扩容。但只升级不降级------一旦用了大房子,绝不搬回小单间(内存浪费?不存在的!)。
2. Hashtable的字典结构
每个元素作为哈希表的键,值为NULL。简单粗暴,但查找速度堪比闪电侠。
五、对比:Set vs 其他数据结构
特性 | Set | List | Sorted Set |
---|---|---|---|
元素唯一性 | ✅ | ❌ | ✅(但分值可重复) |
顺序 | 无序 | 有序(插入顺序) | 有序(按分值排序) |
应用场景 | 去重、集合运算 | 消息队列、时间线 | 排行榜、范围查询 |
六、避坑指南:Set的"七伤拳"
- 大集合的交集操作 :直接对海量数据做
SINTER
可能导致Redis阻塞,建议在从库或客户端处理。 - 内存爆炸 :一次性插入百万元素?Redis可能原地崩溃!建议分批插入或使用
pipeline
。 - 误用排序 :Set本身无序,若需要排序,请召唤Sorted Set。
- 过期策略:依赖惰性删除+定期删除,别指望Redis会主动清理所有过期数据。
七、最佳实践:让Set更"6"
- 合理选择编码:尽量让集合元素为整数且数量≤512,触发intset省内存。
- 慎用
SMEMBERS
:大集合直接获取所有元素可能拖垮网络,改用SSCAN
分批迭代。 - 分布式锁的陷阱 :用
SETNX
时记得加过期时间,避免死锁(血泪教训!)。
八、面试考点:征服面试官的弹药库
-
Q:Set的底层实现?
A:Intset或Hashtable,取决于元素类型和数量。
-
Q:如何实现共同关注?
A:用
SINTER
取交集,时间复杂度O(N*M),大数据量慎用。 -
Q:Set和List的区别?
A:Set无序+唯一,List有序+可重复。
-
Q:Set的集合运算复杂度?
A:交集O(N*M),并集O(N),差集O(N),N为最小集合大小。
九、总结:Set的哲学
Redis的Set就像一把瑞士军刀------简单却强大。无论是社交关系、数据去重,还是随机抽奖,它都能轻松应对。但记住:能力越大,责任越大,合理使用才能避免性能"翻车"。
最后送上一句程序员箴言:
"人生苦短,我用Set;代码易写,内存别炸!"