Redis设计与实现--单机数据库的实现

 1 过期处理

1.1 过期时间设置

expire pexpire expireat pexpireat 可以设置键的过期时间

persist是pexpireat命令的反操作.

1.2 过期键删除策略

1.2.1 定时删除

对内存是最友好的,对CPU不友好;

除此之外,创建一个定时器需要用到Redis服务器中的时间事件,当前时间事件的实现方式是无序链表,查找一个时间事件的事件复杂度为O(N).

1.2.2 惰性删除

对CPU最友好,对内存最不友好.

1.2.3 定期删除

定期删除是前两种策略的折中,每个一段时间执行一次删除过期键操作,并通过限制删除操作执行的时长和频率来减少删除操作对CPU时间的影响.

1.2.4 Redis的过期键删除策略

惰性删除的实现:所有读写命令执行前都会调用expireIfNeeded函数对输入键进行检查;

定期删除的实现:每当Redis的服务器周期操作serverCron函数时,activeExpireCycle函数就会被调用,在规定的时间内,分多次遍历服务器中的各个数据库,从数据库的expires的字典中随机检查一部分键的过期时间,并删除其中的过期键.

1.3 AOF文件,RDB文件,复制对过期键的处理

生成RDB文件时,过期键不会被保存.

载入RDB文件时,过期键对载入RDB文件的主服务器不会造成影响;载入从服务器时,不论键是否过期,都会被载入,然而主从服务器在进行数据同步时,从服务器的数据库会被清空,所以一般而言,过期键对从服务器也不会造成影响.

AOF文件写入时,当过期键被惰性删除或定期删除之后,程序会向AOF文件追加一条DEL命令.

重写AOF文件时,已过期的键不会被保存到重写的AOF文件中.

当服务器处于复制模式下,主服务器删除过期键时,会向所有从服务器发送一个DEL命令;从服务器除非接到主服务器的DEL命令,否则一般读命令,不会删除过期键.

2 RDB持久化

2.1 保存与载入

  • save命令会阻塞Redis服务器进程,
  • bgsave命令会派生出一个子进程,然后由子进程负责创建RDB文件,服务器父进程继续处理命令请求.
  • RDB载入时会处于阻塞状态,直到载入工作完成为止.

  AOF更新频率高于RDB,所以如果开启了AOF功能,服务器优先使用AOF还原,否则使用RDB文件还原.

  执行BGSAVE命令时,SAVE和BGSAVE命令会被拒绝,BGREWIRTEAOF命令会被延迟到BGSAVE命令执行完毕之后;
  执行BGREWRITEAOF命令时,BGSAVE会被服务器拒绝.BGREWRITEAOF和BGSAVE命令都是子进程执行,不允许同时执行只是处于性能考虑.

2.2 保存条件的数据结构

设置保存策略,服务器默认每隔100ms就会检查保存条件是否满足,是的话,则执行BGSAVE命令。

struct redisServer {
    //记录了保存条件的数组
    struct saveparam *saveparams;
    //修改计数器
    long long dirty;
    //上一次执行保存的时间
    time_t lastsave;
};
struct saveparam {
    //秒数
    time_t second;
    //修改数
    int changes;   
}; 

2.3 RDB文件结构

REDIS为5字节,

db_version为4字节, 表示RDB文件的版本号,

check_sum是一个8字节的无符号整数,

2.3.1 databases部分

SELECTED是1字节,

db_number是数据库号,为1,2,5字节,

2.3.2 key_value_paris部分

<未完待续>

3 AOF持久化

命令追加到服务器状态的auto_buf缓冲区的末尾:

struct redisServer{

    //AOF缓冲区
    sds aof_buf;

};

 flushAppendOnlyFile函数用于是否将aof_buf中的内容写入或保存到AOF文件中.appendfsync的默认值为everysec.

3.1 AOF文件重写的实现

REDIS_AOF_REWRITE_ITEMS_PER_CMD常量默认值为64,也就是如果一个键包含了超过64个元素,那么重写程序会用多条SADD命令来记录,并且每条命令设置的元素也为64个;

3.2 AOF后台重写--BGREWRITEAOF命令

Redis将AOF重写程序放在子进程中执行;

目的:子进程重写时,父进程可以继续处理任务;子进程拥有服务器进程的数据副本,使用子进程而非线程,可以在不使用锁的情况下,保证数据的安全.

为了解决重写程序进行中服务器进程同时在写入数据所导致的数据不一致问题,Redis设置了一个重写缓冲区.

当子进程完成AOF重写工作之后,它会向父进程发送一个信号,父进程在接到该信号之后,会调用一个信号处理函数:

1) 将AOF重写缓冲区的所有内容写入到新AOF文件中,这时新AOF文件所保存的数据库状态将和服务器当前的数据库状态一致.

2) 将新的AOF文件进行改名,原子地覆盖现有的AOF文件,完成替换.

在整个AOF后台重写中,只有信号处理函数执行时会对服务器进程造成阻塞,其他时候不会阻塞.

4 事件

4.1 文件事件

Reactor模式

文件处理器以单线程运行,通过使用IO多路复用程序来监听多个套接字.

4.2 时间事件

服务器将所有时间事件都放在一个无序链表里面中.

6 客户端

7 服务器

原文地址:https://www.cnblogs.com/cheungchein/p/8665487.html