redis设计与实现(一)

一:redis的数据库

  服务器中的数据库

      1.int dbnum:决定了服务器数据库的数量,这个数量在初始化服务器的时候决定。默认情况这个值为16。

  切换数据库

      1.redis的客户端都有自己的目标数据库,每当客户端执行数据库的命令时,目标数据库便是这个命令的操作对象,默认情况下客户端目标数据库是0号数据库。但是可以通过 select db 来切换数据库。 客户端redisClient的结构中db属性保存了客户端当前的目标数据库。这个指针指向了redisServer.db数组中的一个元素,即目标数据库。

   

数据库键空间

     1.每个数据库都是由一个redis.h/redisDb结构表示。redisDb结构的dict字典保存了数据库中的所有键值对称为键空间。

         键空间的键是数据库的键,每个键值都是一个字符串对象。

         键空间的值就是数据库的值,每个值都可以是字符串对象,列表对象,集合对象,有序集合对象,散列对象。结构如下

redis设计与实现(一)_第1张图片

     2.读写键空间的维护操作:服务器不仅仅是对键空间的读写进行操作,还会进行一些额外的维护操作

      (1)在读取一个键之后,服务器会根据键值的是否存在来更新服务器键空间的命中和不命中的次数。这个值可以通过keyspace_hits属性和keyspace_misses属性查看。

     (2) 在读取一个键后,服务会更新这个键的LRU(最近一次访问时间),这个值可以计算键的空闲时间

     (3)服务在读取一个键时,发现这个键已经过期,会先删除这个键值,再继续其他操作。 

 

设置键的生存时间或者过期时间 

    (1) 命令:expire  key time:将键key的生存时间设置为time秒

                    pexpire  key time:将键key的生存时间设置为time毫秒

                   expireat key timestamp 将键key的过期时间设置为timestamp所指定的秒数时间戳。

                   pexpireat key timestamp 将键key的过期时间设置为timestamp所指定的毫秒数时间戳。

                 但是前三个命令的本质转换为最后的pexpireat命令来实现的。

  (2)保存过期时间

           redisDb结构expires字典保存了数据库中所有键的过期时间,便成为过期字典。

                键:过期字典的键是一个指针,指向键空间的键对象。这样子的存储键空间和过期字典的键都是指向同一个对象,不会造成内存浪费。

                值:过期字典的值是long类型的整数,存储的是这个键的过期时间(UNIX的毫秒精度的时间戳)

                 redis设计与实现(一)_第2张图片

      (3)判定过期键

             1.检查过期字典是否存在指定的键,如果存在,那么取得键的过期时间

             2.检查当前UNIX时间是否大于键的过期时间,如果是,则键已经过期了。否则,键值未过期。

 

 过期键删除策略:

      (1)策略

            1.定时删除:在设置见得过期时间的同时,创建一个定时器,让定时器在键的过期时间来临是立即执行对键的删除操作。

                 缺点:当过期键过多时,定期删除会占用一部分的CPU时间。会影响服务器正常操作的影响时间和吞吐量。

            2.惰性删除:从键空间获取键时,先检查键值是否过期,如果过期的话,就删除该键。没有过期,就返回该键。

                惰性删除对CPU的时间是最友好的,但是大量的过期键未删除,未造成内存的浪费。

            3.定期删除:每隔一段时间,程序对数据库进行一次检查,删除里面的过期键。

                缺点:执行太频繁或者时间太长,会退化为定删除。执行时间太少会造成内存的浪费。

    (2)redis的删除策略:采用2、3两种方式结合的方式来删除过期策略。

            惰性删除:从键空间获取键时,先检查键值是否过期,如果过期的话,就删除该键。没有过期,就返回该键。

                          redis设计与实现(一)_第3张图片

            定期删除策略:

              redis设计与实现(一)_第4张图片

    

二、RDB持久化

  RDB持久化:是将redis的内存数据,保存在磁盘中,避免数据意外丢失。

 RDB文件的创建与载入

   用于创建RDB文件的命令是save、bgsave

       save命令:会调用服务器的主进程来创建RDB文件,所以主进程会拒绝其他的命令。

       bgsave命令:会创建一个子进程来创建RDB文件,主进程可以继续处理命令请求。

       服务器在载入RDB文件期间,会一直处于阻塞状态,知道载入工作完成为止。

 

  RDB文件结构:

     结构:REDIS、db_version、database、EOF、check_sum      

     REDIS:常量。用于载入文件时,快速检查所载入的文件是否是RDB文件

     db_version: 长度4个字节的整数,记录了RDB文件的版本号

     database:包干零个或者任意多个数据库,以及各个数据库中的键值对数据。

     EOF:1个字节的常量字节。标志着RDB文件正文内容的结束。

     check_sum:对于前四个值的校验。

            database结构:SELECTDB 、db_number、key_value_pairs

           db_number:数据库号码。

           key_value_pairs:保存了数据库中所有的键值对数据。包括键值的过期时间;

   

AOF持久化:

    概念:通过保存Redis服务器所执行的写命令来记录数据库状态。

   1.持久化实现:

         AOF的写入和同步:

                 flushAppendOnlyFile函数,将aof_buf缓冲区中的内容写入和保存AOF文件里面。

                 redis设计与实现(一)_第5张图片

 

2.AOF文件的载入与数据还原

          步骤:

            1.创建一个不带网络的伪客户端(因为redis命令只在redis客户端上下文中执行,而载入AOF是从磁盘中加载,并进行读入和执行的,所以创建一个不带网络的客户端来执行AOF的命令,效果是一样)

            2.从AOF的文件中读取一条命令

           3.使用伪客户端来执行这条命令

           4.重复2、3步,直到AOF文件命令被读取完全。

 

服务器:

   1.一个redis命令请求的过程

       (1)客户端将命令请求发送到服务器

       (2)服务器读取命令请求,并分析出命令参数

       (3)命令执行器根据参数查找命令的实现函数,然后执行实现函数并得出命令回复

       (4)服务器将命令回复返回给客户端

   2.服务器启动的过程

       (1)初始化服务器状态

        (2)载入服务器配置

        (3)初始化服务器数据结构

        (4)还原数据库状态

         (5)执行事件循环

你可能感兴趣的:(redis)