Redis的Set类型就像是一个永远不会重复的魔法口袋。你往里面放东西,它自动帮你过滤掉重复项,只保留独一无二的元素。这种特性让它在处理需要唯一性数据的场景中显得格外得心应手。
Set类型数据结构特点
Set本质上是一个无序的字符串集合。无序意味着你存入元素的顺序和取出的顺序可能完全不同。这和我们熟悉的Java中的HashSet非常相似,底层都是通过哈希表实现的。
我记得第一次使用Set类型时,被它的自动去重特性惊艳到了。当时需要统计网站的唯一访客,传统方法要写很多去重代码,而Redis Set只需要简单地把用户ID往里添加就行。
Set类型支持的最大成员数量是2^32 - 1个,也就是40多亿个元素。这个数量级对于绝大多数应用场景都绰绰有余了。不过在实际使用中,我们更关心的是内存占用问题,毕竟每个元素都是独立存储的。
Set类型常用命令详解
SADD命令用来向集合添加元素:
SADD key member [member ...]
添加成功返回新增元素数量,已存在的元素会被忽略。这个命令是原子性的,多个客户端同时操作时不会出现竞态条件。
SMEMBERS能够获取集合中的所有成员:
SMEMBERS key
但要注意,当集合很大时,这个命令可能会阻塞Redis服务器。我曾经在一个包含百万级元素的集合上使用这个命令,结果导致服务短暂卡顿。
SISMEMBER检查元素是否存在于集合中:
SISMEMBER key member
返回1表示存在,0表示不存在。这个操作的复杂度是O(1),速度非常快。
SCARD获取集合的基数(元素个数):
SCARD key
这个命令在统计场景中特别有用,而且时间复杂度也是O(1)。
SREM从集合中移除指定元素:
SREM key member [member ...]
返回实际移除的元素数量。不存在的元素会被忽略,不会报错。
Set类型适用场景分析
标签系统是Set类型的经典应用。每个标签对应一个Set,用户ID作为集合成员。这样既能保证每个用户对同一个标签只标记一次,又能快速统计标签下的用户数量。
社交关系存储也很适合。用户的好友列表、关注列表天然需要去重,Set类型正好满足这个需求。计算共同好友只需要一个SINTER命令就能完成。

抽奖活动的去重机制用Set实现特别简单。参与用户的ID存入Set,自动避免重复参与。开奖时用SRANDMEMBER随机抽取,既公平又高效。
数据排重在数据清洗过程中经常用到。比如爬虫系统需要判断URL是否已经爬取过,将已爬取的URL存入Set,新URL先检查是否存在再决定是否爬取。
Set类型的这些特性让它成为Redis中最实用的数据结构之一。它的自动去重和集合运算能力,在很多业务场景中都能显著简化代码逻辑,提升开发效率。
<groupId>redis.clients</groupId>
<artifactId>jedis</artifactId>
<version>4.4.0</version>
// 为用户添加标签 jedis.sadd("user:1001:tags", "high_spender", "tech_lover", "fast_shipping");
// 批量操作用户标签 String[] newTags = {"mobile_user", "weekend_shopper"}; jedis.sadd("user:1001:tags", newTags);

// 检查用户是否拥有某个标签 boolean isTechLover = jedis.sismember("user:1001:tags", "tech_lover");
// 获取用户所有标签
Set
// 强制使用intset编码的小集合示例 for (int i = 0; i < 100; i++) {
jedis.sadd("small:set", String.valueOf(i));
}
// 检查编码类型 String encoding = jedis.objectEncoding("small:set"); // 返回 "intset" 或 "hashtable"
// 找出两个用户的共同兴趣
Set
// 多集合交集计算共同好友
Set
"user:1001:friends",
"user:1002:friends",
"user:1003:friends"
);