Redis中的数据库实现和键的相关操作实现原理

132 阅读4分钟

文章目录


Redis数据库


1. 表示形式

Redis中所有的数据库都保存在服务器状态RedisServer结构的db数组中,db数组中的每一个元素表示一个具体的数据库,每个数据库又是使用redisDb结构表示。Redis默认初始化的数据库数量为16,该值会保存在redisServer的dbnum字段中。如下所示:


image.png

用于可以通过修改redis.conf中的databases来设置数据库的数量。

# Set the number of databases. The default database is DB 0, you can select
# a different one on a per-connection basis using SELECT <dbid> where
# dbid is a number between 0 and 'databases'-1
databases 16

用户在使用Redis时,默认操作的是0号数据库。如果用户想要操作其他的数据库,可以使用SELECT命令来进行转换,底层通过修改RedisClient结构的db指针来指向具体指定的数据库。


image.png


2. 键的操作

Redis是一个key-value形式的NoSQL数据库,其中键总是一个字符串,而value可以是所支持的其他任意类型。对于Redis的底层来说,redisDb中的dict字典(键空间)用来保存对应额key-value对,expires字典用来保存对应的key的过期时间。


image.png

针对于键的常见操作有:

  • 添加:将一个新的键值对添加到dict字典中
  • 删除:删除dict字典中对应的键所对应的键值对
  • 更新:更新dict字典中指定的键所对应的值
  • 取值:根据指定的键从dict中获取相应的值

Redis中提供了不同的命令来设置key的过期时间或是生存时间,如下所示:

  • EXPIRE:将键的生存时间设置为ttl秒
  • PEXPIRE:将键的生存时间设置为ttl毫秒
  • EXPIREAT:将键的过期时间设置为timestamp所指定的秒数时间戳
  • PEXPIREAT:将键的过期时间设置为timestamp所指定的毫秒数时间戳

但是,Redis底层最终都是使用PEXPIREAT命令来设置键的过期时间,具体的过期时间保存在redisDb的expires字典中。字典的键是一个指针,指向对应的键对象,值为对应的过期时间(毫秒精度的UNIX时间戳)。


image.png

具体判定一个键是否过期需要经过以下两步:

  • 检查给定的键在expires中是否存在;如果存在,获取键的过期时间
  • 检查当前UNIX时间戳是否大于过期时间;如果是,表示已经过期,否则,未过期

另外,用户也可以使用PERSIST命令移除指定键的过期时间,以及使用TTL和PTTL计算键的剩余生存时间。


3. 持久化对过期键的处理

Redis支持RDB和AOF两种持久化方式,它们针对于过期的键分别有不同的处理策略。对于RDB持久化来说:

  • 生成RDB文件时,程序会对数据库中的键进行检查,已经过期的键是不会保存到生成的RDB文件中
  • 主节点载入RDB文件时,程序会对键进行检查,已经过期的键不会被载入
  • 从节点载入RDB文件时,不管键是否过期都会被载入

而对于AOF这种追加写命令的持久化方式来说:

  • AOF写入时,当过期的键被删除之后,程序会向AOF文件追加一条DEL命令,显示记录键已被删除
  • AOF重放时,程序会对键进行检查,已经过期的键不会被保存到重放后的AOF文件

4. 主从复制对过期键的处理

当主节点删除一个键之后,它会显式的向所有的从节点发送一个DEL命令,通知从节点也删除相应的键。对于从节点来说,它在处理除了主节点发来的DEL命令之外,即时碰到已经过期的键也不会删除,而是正常响应。只有它接受到的是主节点的DEL命令,才会删除对应的过期键。


image.png