redis高可用之RDB持久化

大耗子 2021年01月24日 56次浏览

RDB

  • 因为Redis是内存数据库, 它将自己的数据库状态储存在内存里面, 所以如果不想办法将储存在内存中的数据库状态保存到磁盘里面, 那么一旦服务器进程退出, 服务器中的数据库状态也会消失不见。
  • 为了解决这个问题, Redis提供了RDB持久化功能, 这个功能可以将Redis在内存中的数据库状态保存到磁盘里面, 避免数据意外丢失。
  • RDB持久化既可以手动执行, 也可以根据服务器配置选项定期执行, 该功能可以将某个时间点上的数据库状态保存到一个RDB文件中。
  • RDB持久化功能所生成的RDB文件是一个经过压缩的二进制文件, 通过该文件可以还原生成RDB文件时的数据库状态。如果里面有键过期,加载的时候会忽略过期键。

RDB文件的创建

有两个Redis命令可以用于生成RDB文件, 一个是SAVE, 另一个是BGSAVE

  • SAVE命令会阻塞Redis服务器进程, 直到RDB文件创建完毕为止, 在服务器进程阻塞期间, 服务器不能处理任何命令请求。执行完SAVE后,重新开始接收命令请求之后,客户端发送的命令才会被处理。
  • BGSAVE命令会派生出一个子进程, 然后由子进程负责创建RDB文件, 服务器进程(父进程) 继续处理命令请求。
  • 使用BGSAVE命令期间,不能使用SAVE,BGSAVE与BGREWRITEAOF。save与bgsave不让执行是因为会出现条件竞争,bgrewriteaof不让执行是因为两个都是写磁盘命令,同时写并不会让性能得到提升,还不如一个一个来。

RDB文件的载入

  • RDB文件的载入工作是在服务器启动时自动执行的, 所以Redis并没有专门用于载入RDB文件的命令, 只要Redis服务器在启动时检测到RDB文件存在, 它就会自动载入RDB文件。
  • 由于AOF文件的更新频率比RDB的更好,Redis中如果开启了AOF,那么会优先加载AOF文件来还原数据。关闭AOF才会加载RDB的数据文件。
  • 在载入RDB文件的时候,服务器会一致处于阻塞状态,直到载入工作完成为止。

自动间隔性保存

  • 由于BGSAVE命令是通过子进程去保存数据,不会阻塞主服务进程,所以redis允许用户设置服务器配置的save选项, 让服务器每隔一段时间自动执行一次BGSAVE命令。
  • 用户可以通过save选项设置多个保存条件, 但只要其中任意一个条件被满足, 服务器就会执行BGSAVE命令。
    例如:
save 900 1   	// 服务器在900秒之内, 对数据库进行了至少1次修改。
save 300 10 	// 服务器在300秒之内, 对数据库进行了至少10次修改。
save 60 10000	// 服务器在60秒之内, 对数据库进行了至少10000次修改。

保存条件

  • 配置的条件会保存在如下结构体中,
struct saveparam {
    time_t seconds; // 秒数
    int changes;	// 修改次数
};

// 成员太多,就不一一展示了
struct redisServer {
    // ...
    //记录了保存条件的数组
    struct saveparam *saveparams;
    //修改计数器
	long long dirty;
    //上一次执行保存的时间
    time_t lastsave;
    // ...
};
  • 除了saveparams数组之外, 服务器状态还维持着一个dirty计数器, 以及一个lastsave属性:
  • dirty计数器记录距离上一次成功执行SAVE命令或者BGSAVE命令之后, 服务器对数据库状态(服务器中的所有数据库) 进行了多少次修改(包括写入、 删除、 更新等操作) 。
  • lastsave属性是一个UNIX时间戳, 记录了服务器上一次成功执行SAVE命令或者BGSAVE命令的时间。
  • Redis的服务器周期性操作函数serverCron默认每隔100毫秒就会执行一次, 该函数用于对正在运行的服务器进行维护, 它的其中一项工作就是检查save选项所设置的保存条件是否已经满足, 如果满足的话, 就执行BGSAVE命令。