Redis 的 SADD
和 SREM
命令分别用于集合(Set)数据结构的添加成员和删除成员操作。了解它们的源码实现有助于深入理解Redis如何高效地处理集合数据类型的操作。
源码位置
这些命令的实现可以在Redis源代码的t_set.c
文件中找到,具体函数为saddCommand
和sremCommand
。
SADD 命令实现
- 命令解析与参数处理:Redis解析客户端发送的命令和参数,确定操作的集合键名以及要添加的成员。
- 键检查与创建:通过
lookupKeyWriteOrReply
函数检查集合键是否存在。如果不存在,会创建一个新的集合。 - 成员添加:对于每个待添加的成员,Redis会使用集合的底层数据结构(通常是
intset
或hashtable
)来执行添加操作。如果是intset
(整数集合),会检查是否需要升级到hashtable
。成员添加操作是原子的,即使在成员已存在的情况下也不会重复添加。 - 返回值:返回实际添加到集合的新成员数量(不包括已存在的成员)。
SREM 命令实现
- 命令解析与参数处理:类似
SADD
,解析命令和参数,确定操作的集合键和要删除的成员。 - 键与成员存在性检查:通过
lookupKeyWriteOrReply
检查集合键是否存在。如果键不存在或不是集合类型,返回错误。接着,尝试从集合中删除指定的成员。 - 成员删除:遍历要删除的成员列表,对于每个成员调用相应的删除逻辑。删除操作会根据集合的编码(
intset
或hashtable
)来执行。如果成员不存在,操作也会被安全忽略。 - 返回值:返回实际从集合中删除的成员数量。
数据结构与编码
- Redis集合可以使用
intset
(当集合中所有成员都是整数且成员数量较少时)或hashtable
(成员较多或有非整数成员)编码。 - 在成员数量增长或成员类型改变时,Redis会自动在
intset
和hashtable
之间转换,以优化内存使用和查询性能。
注意事项
- 这些操作都是原子性的,意味着在多客户端环境下,对同一集合的操作不会相互干扰。
- Redis的单线程模型简化了并发控制,使得集合操作天然具备线程安全特性。
通过阅读saddCommand
和sremCommand
的源码,可以深入理解Redis集合操作的内部机制,包括成员添加与删除的细节,以及Redis如何动态调整集合的编码来适应不同的使用场景。