Redis知识(四)--持久化

引言

  Redis是一个内存数据库,它将自己的数据库状态存在内存里面。如果不想办法将存储在内存的数据库状态保存到磁盘里面,一旦服务器进程退出,那么数据也就不见了。
  为了解决这个问题,Redis提供了RDB和AOF持久化功能,将Redis内存中的数据保存到磁盘里面,避免意外丢失。

一、RDB持久化

  RDB持久化功能所生成的RDB文件是一个经过压缩的二进制文件,通过该文件还可以还原生成RDB文件时的数据库状态。

1、RDB文件的创建与载入

1.1、RDB的创建

  有两个命令可以用于生成RDB文件:SAVEBGSAVE
  SAVE命令会阻塞Redis服务器进程,直到RDB文件创建完毕,在服务器进程阻塞期间,服务器不能处理任何命令请求。
  BGSAVE命令会派生出一个子进程,然后由子进程负责创建RDB文件,服务器进程(父进程)继续处理命令请求。

1.2、RDB的载入

  Redis没有专门用于载入RDB文件的命令,只要服务器启动时检测到RDB的存在,就会自动载入RDB文件。在RDB文件载入期间,服务器会一直处于阻塞状态。 成功载入后日志如下:
在这里插入图片描述

1.3、RDB载入的条件

  AOF文件的更新频率通常比RDB高,所以对于服务器启动过程载入RDB的条件为:

  1. 如果服务器开启了AOF持久化功能,服务器会优先使用AOF文件来还原数据库状态
  2. 只有在AOF持久化功能处于关闭状态时,服务器才会使用RDB文件来还原数据库状态
    在这里插入图片描述

2、RDB的自动间隔性保存

  通过save选项设置多个保存条件,可以让服务器每隔一段时间自动执行BGSAVE命令。比如,设置如下配置:

save 900 1          // 900秒内,对数据库进行了至少1次修改
save 300 10        // 300秒内,对数据库进行了至少10次修改
save 60 10000 // 60秒内,对服务器进行了至少10000次修改

  只要满足3个条件中任意一个,BGSAVE命令就会执行。
  默认情况下,Redis的周期操作函数serverCron每隔100毫秒会执行一次,检查是否满足条件进行持久化操作。 如果满足的话,就会执行BGSAVE命令。
  save选项所设置的保存条件,保存在服务器状态redisServer结构的saveparams属性中;此外dirty属性和lastsave属性用于辅助持久化操作:

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

struct saveparam {
	// 秒数
	time_t seconds;
	// 修改数
	int changes;
}

在这里插入图片描述

二、AOF持久化

  AOF持久化是通过保存Redis服务器所执行的写命令来记录数据库状态。
在这里插入图片描述

1、AOF的实现

  AOF持久化功能的实现可以分为:命令追加(append)、文件写入、文件同步(sync)

struct redisServer{
	// ...
	// AOF缓冲区
	sds aof_buf;
	// ...
}

命令追加:当AOF持久化功能打开时,服务器在执行完一个写命令后,会以协议格式将被执行的写命令追加到服务器状态的aof_buf缓冲区的末尾

文件写入与同步:Redis服务器进程是一个事件循环,每次事件循环结束之前,会调用flushAppendOnlyFile函数,考虑是否将aof_buf缓冲区的内容写入到AOF文件中。flushAppendOnlyFile函数行为由服务器配置appendfsync选项的值来决定。

在这里插入图片描述

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

  AOF文件包含了重建数据库状态所需的所有写命令,所以服务器只需要重新执行一遍AOF文件中的所有命令,就可以还原到服务器关闭之前的数据库状态。
  读取AOF文件并还原步骤如下:

  1. 创建一个不带网络连接的伪客户端
  2. 从AOF文件中分析并读取出一条写命令
  3. 使用伪客户端执行被读出的写命令
  4. 重复步骤2和3,知道AOF所有命令都处理完

在这里插入图片描述

3、AOF重写

  随着写入命令的增加,AOF文件内容越来越多,文件体积越来越大。体积过大的AOF会影响到Redis服务器甚至宿主机器,而且使用AOF还原所需的时间也越多。针对这个问题,Redis提供了文件重写功能:创建一个新的AOF来替代现有AOF文件,新AOF不会有任何浪费空间的冗余命令。

3.1、AOF重写原理

  AOF重写并不需要依赖现有的AOF文件,而是通过读取服务器当前的数据库状态来实现:首先从数据库中读取键现在的值,然后用一条命令记录该键值对,代替之前这个键值对的多条命令。
  AOF重写使用BGREWRITEAOF命令,该命令会创建一个子进程来完成AOF重写。Redis服务器设置了一个AOF重写缓冲区,这个缓冲区在创建子进程之后开始使用。重写的过程如下:

  1. 当Redis执行完一个写命令后,同时往AOF缓冲区和AOF重写缓冲区发送。
    在这里插入图片描述
  2. 当子进程完成重写后,向父进程发送信号
  3. 父进程接收到完成信号后,将AOF重写缓冲区的写命令追加到新的AOF文件中
  4. 父进程用新AOF文件覆盖旧AOF。整个重写过程就算完成了。
    在这里插入图片描述

3.2、AOF自动重写触发条件

  AOF功能开启的情况下,会维持三个变量:

  • aof_current_size:当前AOF文件大小
  • aof_rewrite_base_size:最后一次AOF重写之后,AOF文件大小
  • aof_rewrite_perc:增长百分比

  同时redis配置中,有两个属性:

  • auto-aof-rewrite-min-size:运行AOF重写时文件最小体积, 默认为64MB
  • auto-aof-rewrite-percentage:当前AOF文件空间( aof_current_size) 和上一次重写后AOF文件空间(aof_rewrite_base_size) 的比,默认100

  自动触发AOF重写条件:

  1. 当前没有RDB或AOF持久化操作在执行
  2. 没有BGREWRITEAOF在进行
  3. 当前AOF大小大于配置的最小AOF重写体积(auto-aof-rewrite-min-size),并且AOF增长百分比大于等于配置增长百分比(auto-aof-rewrite-percentage)

总结

1、Redis没有专门命令载入RDB文件,服务器启动初始化时,会自动载入RDB;载入RDB前提是服务器没有开启AOF持久化功能,否则会优先载入AOF
2、SAVE保存RDB会使服务器阻塞,BGSAVE由子进程执行保存操作所以不会阻塞
3、Redis默认每隔100毫秒检查是否满足条件保存RDB,满足则进行保存
4、服务器每执行完一个写命令,会往AOF缓冲区发送该写命令;通过Redis的事件循环调用flushAppendOnlyFile函数将缓冲区的写命令同步到AOF文件中,同步时机服务器由配置appendfsync选项的值来决定
5、AOF重写是通过数据库中的键值对来完成;重写过程中会启用AOF重写缓冲区来保存服务器接收并处理的写命令

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值