Redis持久化
Redis为键值对提供了持久化功能,并且有两种持久化方式,分别是 ,RDB和AOF方式
RDB
保存
在Redis中有两个命令可以生成RDB文件,SAVE和BGSAVE。
- SAVE命令会阻塞Redi服务器进程,直到RDB文件创建完毕为止,在服务器阻塞期间不能处理任何请求。
- BGSAVE命令则不会阻塞Redis服务器进程,它会fork一个子进程来执行持久化操作,然后父进程继续处理请求命令。
对于SAVE命令,会拒绝掉所有的其他服务器命令,包括SAVE,BGSAVE。 BGSAVE虽然不会阻塞Redis服务器进程,但是它也会拒绝掉过来的SAVE和BGSAVE命令,如果有AOFREWRITE命令的话,会等待BGSAVE执行完成后再执行AOF重写命令。
在Redis中,它允许用户通过设置服务器配置的save选项,让服务器每隔一段时间就自动执行一次BGSAVE命令,因为此命令不会阻塞服务器进程。 用于可以设置多个条件,只要其中一个满足就会执行BGSAVE命令。 举个例子 : 假设有如下配置:
save 900 1
save 300 10
save 60 10000
那么只要满足一下三个条件之一,服务器就会执行BGSAVE命令。
- 在900秒之内,对数据库进行了一次修改
- 在300秒之内,对数据库进行了至少10次修改
- 在60秒之内,对数据库进行了至少10000次修改
在Redis中,会把这些保存条件保存到redisServer中的saveparams属性中,这是一个数组。如下图
并且,除了saveparams数组之外,服务器状态还维护了一个dirty计数器以及一个lastsave属性。
- dirty计数器保存着距离上一次成功执行save命令或bgsave命令之后,服务器对数据库状态进行了多少次修改
- lastsave属性是一个时间戳,记录着上一次执行保存的时间。
Redis中的周期性操作函数默认每隔100ms就会执行一次,该函数用来对正在运行的服务器进行维护,其中有一项就是检查save条件是否成立。 主要就是判断dirty和lastsave是否满足saveparams数组中的任意一对条件。如果满足任意一个条件,那么就执行BGSAVE操作,否则,就什么都不做。
载入
Redis没有载入命令,它会在服务器启动的时候检查是否有RDB文件,如果有则会自动载入。但是如果有AOF文件的时候,就不会载入RDB文件,则会载入AOF文键。
AOF
Redis还提供了AOF(append only file)持久化的功能。与RDB通过保存数据库的键值对数据不同,AOF持久化是通过保存Redis服务器所执行的写命令来记录数据库状态的。
AOF持久化功能可以分为命令追加、文件写入、文件同步三个步骤。 当AOF持久化功能打开时,服务器每执行完一个写命令,会将被执行的写命令追加到服务器状态的aof_buf缓冲区的末尾。
然后会根据用户对于AOF的配置来决定什么时候写入和同步到aof磁盘。 对于aof配置有三种选项
- always 将aof_buf所有内容写入并同步到aof文件
- everysec 将aof_buf所有内容写入aof文件,如果上次同步时间到现在超过一秒,则进行同步到aof文件
- no 将aof_buf所有内容写入到sof文件,不手动进行同步,何时同步由操作系统来决定。
这里写入和同步又是写入什么,又同步什么呢? 写入就是讲aof_buf缓冲区的内容全部都追加到aof文件中。 然后在将文件中的内容同步到系统磁盘上。 写入不是已经写进去了么,为什么还要同步呢? 这啊,是因为现代操作系统是有一个磁盘缓冲区的,等到这个缓冲区都满了或者超过时间了,才会真正的将缓冲区的数据真正写入到磁盘中。虽然这样效率高,但是可能会丢失更新,所以说提供了一个函数强制将缓冲区刷新回磁盘。用来确保写入数据的安全性。
载入
AOF文件里包含了重建数据库所需的所有命令,所以服务器只需要读取aof所有的写命令并且执行一遍,就可以恢复到之前的状态了。具体流程
AOF重写
因为AOF通过保存写命令来记录数据库状态的。因此,AOF文件会越来越多,并且可能会有很多重复的。比如说对某一个键进行了大量的修改,那么AOF文件就会有大量关于此键的记录,会对恢复造成很大的负担。 因此,有了AOF重写功能。
AOF重写并不会对旧的AOF进行读取,它是通过读取当前服务器的数据来进行新的AOF进行写入的。也就是说,会用最少的语句来对AOF文件进行更新,新的AOF文件一定只保存有用的信息,不会出现很多条命令对一个键值对的写入和修改,大大减少了AOF文件的大小。
并且在AOF重写的时候,定义了一个常量,避免客户端的缓冲区溢出,重写程序在处理列表、哈希表、集合、有序集合这四种元素的时候,会先判断元素数量是否太大,如果他打则会分成多条命令来写入。而不单单是一条命令。目前,这个值设置为64.
AOF是后台实现的,也就是说是创建一个子进程,在子进程中进行AOF重写的,但是这个时候如果有新的写命令该怎么办呢,在Redis中,如果在执行后台AOF重写的过程中,写命令不仅会把命令写入AOF缓冲区,还会将命令写入AOF重写缓冲区。这个重写缓冲区的内容将在AOF重写完成之后添加到AOF文件末尾。
当子进程执行重写完毕之后,会向父进程发送一个信号,表示重写完成,这个时候父进程会将AOF重写缓冲区的内容全部写入新的AOF文件中,并且对新的文件改名,原子的覆盖旧的AOF文件,完成AOF重写。