我知道点redis-单机数据库(RDB持久化)

10.1 RDB文件的创建和载入

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

10.1.1 创建

SAVE

SAVE命令会阻塞Redis服务器进程,直到RDB文件创建完毕,在服务器进程阻塞期间,服务器不能处理任何请求。

BGSAVE

BGSAVE命令会派生一个subprocess,然后由子进程负责创建RDB文件,父进程继续处理命令请求。

因为BGSAVE命令的保存工作是由subprocess执行的,所以在subprocess创建RDB file的过程中,Redis server仍然可以继续处理client的命令请求。但是在BGSAVE命令执行期间,server处理SAVEBGSAVEBGREWRITEAOF三个命令的方式会和平时有所不同。

  • 首先,在BGSAVE命令执行期间,SAVEBGSAVE命令将被reject。
  • 其次,在BGSAVE命令执行期间,BGREWRITEAOFBGSAVE两个命令不能同时执行。

10.1.2 载入

RDB文件的载入工作是在服务器启动时自动执行的,所以Redis没有专门用于载入RDB文件的命令。

另外,值得一提的是,因为AOF文件的更新频率通常比RDB文件的更新频率高,所以:

  • 如果服务器开启了AOF持久化功能,那么server会优先使用AOF file来reduction db status;
  • 只有在AOF 持久化功能处于close状态时,server才会使用RDB file 来 reduction db status。

10.2 自动间隔性保存

因为BGSAVE命令可以在不阻塞server process的情况下执行,所以Redis允许用户通过设置server配置的save选项,让服务器每隔一段时间自动执行一次BGSAVE则不会。

user可以通过save选项设置多个保存条件,但只要其中任意一个条件被满足,server就会执行BGSAVE命令。

save 900 1表示服务器在900s内,对db进行了至少1次就修改。

10.2.1 设置保存条件

当Redis server启动时,用户可以通过指定配置文件或者传入启动参数的方式配置save选项。server根据save选项所设置的保存条件,设置server状态redisServersaveparams属性:

struct redisServer {

	// ...
	
	// 记录保存条件的数组
	struct saveparam *saveparams;
	
	// ...

}

saveparams属性是个数组,数组中的每个元素都是一个saveparam结构,每个saveparam结构都保存了一个save选项设置的保存条件:

struct saveparam {

	// 秒数
	time_t seconds;
	
	// 修改数
	int changes;

}

10.2.2 dirty计数器和lastsave属性

除了saveparams数组之外,服务器状态还维持着一个dirty计数器,以及一个lastsave属性:

  • dirty计数器记录着距离上一次成功SAVE命令或者BGSAVE命令之后,服务器对db status进行了多少次修改。
  • lastsave属性属于一个UNIX时间戳,记录了服务次上一次成功执行SAVE命令或者BGSAVE命令的时间.
code
struct redisServer {
	
	// ...
	
	// 修改计数器
	long long dirty;
	
	// 上一次执行保存的时间
	time_t lastsave;
	
	// ...
}

当Server成功执行一次db修改命令,dirty就会更新:命令修改了多少次db,dirty值就是多少。

10.2.3 检查保存条件是否满足

Redis的服务器周期性操作函数serverCron默认每隔100ms就会执行一次,该函数用于对正在运行的server进行维护,它的其中一项工作就是检查save现象所设置的保存条件是否已经满足,如果满足的话,就执行BGSAVE命令。

// 伪代码
def serverCron() :
	
	# ...
	
	# 遍历所有保存条件
	for saveparam in server.saveparams:
	
		# 计算距离上次执行保存操作有多少秒
		save_interval = unixtime_now() - server.lastsave
		
		# 如果数据库状态的修改次数超过条件所设置的次数
		# 并且距离上次保存的时间超过条件所设置的时间
		# 那么执行保存操作
		if server.dirty >= saveparam.changes and \
			save_interval > saveparam.seconds:
				
				BGSAVE()
	# ...

程序会遍历病检查saveparams数组中的所有保存条件,只要有任意一个条件被满足,那么server就会执行BGSAVE命令。

以上就是Redis server根据save选项所设置的保存条件,自动执行BGSAVE命令,进行间隔性数据保存的实现原理。