【redis】redis操作set类型的key发生了什么?

以下是关于Redis操作(添加、删除、修改、查询)Set类型key的完整过程,包括引用源码的数据、时序图、磁盘IO读写、数据长度限制、线程安全控制和故障处理机制。


数据结构


时序图

以下是Redis操作Set类型key的时序图:

Redis Client Redis Server SADD myset "apple" "banana" 2 SMEMBERS myset ["apple", "banana"] SREM myset "apple" 1 SMEMBERS myset ["banana"] DEL myset 1 Redis Client Redis Server

(一)添加Set类型key

1. 客户端发送命令

客户端通过Redis客户端库发送SADD命令,格式为:

SADD key member1 [member2 ...]

例如:

SADD myset "apple" "banana" "cherry"
2. 服务器处理命令

Redis服务器接收到SADD命令后,执行以下操作[65]:

  • 检查键是否存在,如果不存在则创建一个新的Set对象。
  • 将成员逐个添加到Set中。如果成员已存在,则不会重复添加。
  • 如果添加了新成员,更新键的过期时间(如果存在)。
3. 数据存储过程
  • 键的存储:键通过字典(Dictionary)存储,字典基于哈希表实现[64]。
  • 值的存储:Set类型的值可以使用两种编码方式:
    • intset:如果所有成员都是整数且数量较少(默认限制为512个),Redis会使用intset(整数集合)编码[65]。
    • hashtable:如果成员数量超过限制或包含非整数成员,Redis会切换到hashtable编码[65]。
4. 返回结果

命令执行完成后,Redis返回成功添加的成员数量。


(二)删除Set类型key

1. 客户端发送命令

客户端发送DEL命令删除键:

DEL key
2. 服务器处理命令

Redis服务器接收到DEL命令后:

  • 查找指定的键,如果键存在,则从字典中删除该键[64]。
  • 如果键不存在,返回0;如果删除成功,返回1
3. 数据删除过程
  • Redis通过字典的dictDel函数删除键值对[64]。
  • 如果键对应的值是大对象,可以使用UNLINK命令异步删除,避免阻塞主线程[64]。
4. 返回结果

命令执行完成后,Redis返回删除的键的数量。


(三)修改Set类型key

1. 客户端发送命令

客户端发送SADDSREM命令修改Set的内容:

SADD key new_member
SREM key member_to_remove
2. 服务器处理命令

Redis服务器接收到命令后:

  • 使用SADD命令将新成员添加到Set中[65]。
  • 使用SREM命令从Set中移除指定成员[65]。
3. 数据更新过程
  • 如果Set使用intset编码且成员数量超过限制,Redis会自动将其转换为hashtable编码[65]。
  • 如果成员被移除后Set为空,Redis会自动删除该键[64]。
4. 返回结果

命令执行完成后,Redis返回成功操作的成员数量。


(四)查询Set类型key

1. 客户端发送命令

客户端发送SMEMBERSSISMEMBER命令查询Set的内容:

SMEMBERS key
SISMEMBER key member
2. 服务器处理命令

Redis服务器接收到命令后:

  • 使用SMEMBERS命令返回Set中的所有成员[65]。
  • 使用SISMEMBER命令检查指定成员是否存在于Set中[65]。
3. 数据查询过程
  • Redis通过字典的dictFind函数查找键,并返回对应的值[64]。
  • 如果Set使用intset编码,Redis会通过二分查找快速定位成员[65]。
4. 返回结果

命令执行完成后,Redis返回查询结果。


持久化

Redis主要是一个内存存储系统,但为了持久化数据,它支持以下两种持久化机制[66]:

(一)RDB(Redis Database File)

  • RDB是Redis的快照持久化机制,它会定期将内存中的数据写入磁盘,生成一个RDB文件[66]。
  • 当添加或更新Set类型的键值对时,Redis会根据配置的策略(如save选项)触发RDB持久化[66]。

(二)AOF(Append Only File)

  • AOF是Redis的追加文件持久化机制,它会将每个写操作追加到AOF文件中[66]。
  • 当执行SADDSREMDEL命令时,Redis会将该操作追加到AOF文件中[66]。

数据长度限制

Redis对Set类型key的值大小有限制[66]:

  • 单个Set类型的值最大长度为512MB。
  • 如果Set中包含大量成员,可能会导致性能问题或内存不足[66]。

优化建议:

  • 对于较大的Set,可以考虑分片存储,将数据分布在多个键中[66]。
  • 使用Redis集群将数据分布在多个节点上,增加总的内存容量[66]。

线程安全控制

Redis是单线程的,所有命令的执行都是原子性的[68]。然而,在高并发场景下,客户端需要确保操作的线程安全性[68]。

(一)使用Lua脚本

Lua脚本在Redis中是原子性执行的,可以确保操作的线程安全性[68]。例如:

-- 检查成员是否存在于Set中
local exists = redis.call("SISMEMBER", KEYS[1], ARGV[1])
if exists == 1 then
    return 1
else
    return 0
end

(二)使用分布式锁

在分布式环境中,可以使用Redis的SETNX命令实现分布式锁[68]。例如:

SETNX lock_key 1 EX 10

故障处理机制

(一)大Key删除

  • 同步删除:使用DEL命令直接删除大Key,可能会阻塞主线程[64]。
  • 异步删除:使用UNLINK命令异步删除大Key,Redis会在后台逐步释放内存[64]。

(二)内存不足

  • 如果Redis内存不足,可以配置maxmemory策略,自动淘汰旧数据[66]。
  • 使用MEMORY PURGE命令释放未使用的内存[66]。

(三)数据丢失

  • 启用RDB和AOF持久化机制,确保数据在故障时能够恢复[66]。

接口

Redis操作Set类型key的过程包括:

  1. 添加:通过SADD命令创建或更新Set类型的键值对[65]。
  2. 删除:通过DELUNLINK命令删除键[64]。
  3. 修改:通过SADDSREM命令更新Set的内容[65]。
  4. 查询:通过SMEMBERSSISMEMBER命令获取Set的信息[65]。

Redis通过高效的哈希表和动态数据结构,实现了快速的Set操作。同时,通过RDB和AOF机制,Redis确保了数据的持久化。对于大Key和内存不足等问题,Redis提供了多种优化和故障处理机制,保证系统的稳定性和性能。

你可能感兴趣的:(缓存,系统设计,redis,数据库)