Redis Set 是一种无序且元素唯一的字符串集合,底层通过 intset 或哈希表实现,具备 O(1) 时间复杂度的增删查能力。本文将拆解其存储结构切换逻辑、核心命令用法及典型业务场景,帮助你在抽奖去重、共同关注等需求中做出合理选型。
Set 集合核心特性与容量限制
Redis Set(集合)中的成员均为字符串类型,遵循无序排列且不可重复的规则。由于底层基于哈希映射表实现,其添加、删除和查找操作的时间复杂度均为 O(1)。单个集合最多可容纳 2^32 - 1 个成员(约 40 多亿个)。
当集合中最后一个成员被删除时,Redis 会自动回收该键对应的底层数据结构。集合的“自动去重”特性使其非常适合需要唯一性校验的场景,例如在抽奖系统中过滤已中奖用户 ID,防止重复中奖。
intset 底层结构与编码升级机制
Redis Set 采用两种底层存储结构:intset(整数集合)与 hash table(哈希表)。当满足以下两个条件时,Redis 会使用 intset 以节省内存:
- 集合内所有成员均为整数值;
- 集合内成员数量不超过 512 个。
一旦插入非整数或元素数量超过 512,Redis 会自动将底层结构升级为哈希表。
intset 的结构体定义如下:
typedef struct intset { uint32_t encoding; // 编码方式,默认为 INTSET_ENC_INT16 uint32_t length; // 集合内成员总个数 int8_t contents[]; // 实际存储成员的数组,数值从小到大有序排列} intset;- encoding:指定编码格式,包含 INTSET_ENC_INT16、INTSET_ENC_INT32 和 INTSET_ENC_INT64 三种。Redis 会根据插入整数的实际大小动态选择编码,以最小化内存占用。当新插入的整数超出当前编码范围时,intset 会触发编码升级并重新分配内存。
- length:记录 contents 数组中的成员总数。
- contents:有序存储成员的数组,元素按从小到大排列且不允许重复。
intset 结构示意图如下:

Set 常用命令速查表
| 命令 | 说明 |
|---|---|
| SADD key member [member ...] | 向集合添加一个或多个元素,自动去重 |
| SCARD key | 返回集合中元素个数 |
| SDIFF key1 [key2] | 返回两个或多个集合的差集 |
| SDIFFSTORE destination key1 [key2] | 计算差集并将结果保存到指定集合 |
| SINTER key1 [key2] | 返回两个或多个集合的交集 |
| SINTERSTORE destination key1 [key2] | 计算交集并将结果保存到指定集合 |
| SISMEMBER key member | 判断指定元素是否存在于集合中 |
| SMEMBERS key | 返回集合中所有元素 |
| SMOVE source destination member | 将元素从源集合移动到目标集合 |
| SPOP key [count] | 随机弹出指定数量的元素 |
| SRANDMEMBER key [count] | 随机返回指定数量的元素,默认返回 1 个 |
| SREM key member [member ...] | 删除一个或多个元素,不存在的元素自动忽略 |
| SUNION key1 [key2] | 返回两个或多个集合的并集 |
| SUNIONSTORE destination key1 [key2] | 计算并集并将结果保存到指定集合 |
| SSCAN key cursor [MATCH pattern] [COUNT count] | 迭代遍历集合中的元素 |
命令实战与业务场景演示
以“用户共同关注”场景为例,user:1 与 user:2 分别关注了不同的编程技术,通过 Set 命令可快速计算交集、并集并管理成员:
# 创建集合并添加多个成员127.0.0.1:6379> SADD user:1 python java mysql(integer) 3127.0.0.1:6379> SADD user:2 python c redis(integer) 3# 求交集:找出共同关注的技术127.0.0.1:6379> SINTER user:1 user:21) "python"# 求并集:合并所有关注的技术127.0.0.1:6379> SUNION user:1 user:21) "java"2) "python"3) "mysql"4) "redis"5) "c"# 查看集合所有成员127.0.0.1:6379> SMEMBERS user:11) "mysql"2) "java"3) "python"# 计算并集并保存到新集合 user:3127.0.0.1:6379> SUNIONSTORE user:3 user:1 user:2(integer) 5127.0.0.1:6379> SMEMBERS user:31) "java"2) "python"3) "mysql"4) "redis"5) "c"# 随机弹出元素127.0.0.1:6379> SPOP user:1 11) "python"127.0.0.1:6379> SPOP user:1 21) "mysql"2) "java"# 查看集合元素数量127.0.0.1:6379> SCARD user:2(integer) 3# 迭代遍历集合127.0.0.1:6379> SSCAN user:3 01) "0"2) 1) "mysql" 2) "redis" 3) "java" 4) "python" 5) "c"
如需在线验证命令效果,可访问 https://try.redis.io/;完整命令文档请参考 https://redis.io/commands。
