Redis持久化方式

redis持久化方式

  • 持久化的两种方式
  • RDB文件的创建与载入
  • RDB文件载入时的服务器状态
  • 自动间隔性保存
  • AOF持久化
  • AOF持久化的实现

持久化的两种方式

  • RDB(Redis Database): RDB持久化,是对redis中的数据执行周期性的持久化。(指定的时间间隔能对你的数据进行快照存储)
  • AOF : AOF 机制对每条写入命令作为日志,以append-only的模式写入一个日志文件中,在redis重启的时候,可以通过回放AOF日志中的写入指令来重新构建整个数据集。(每一个收到写命令都通过write函数追加到文件中)
    如果同时使用了RDB和AOF两种持久化机制,那么在redis重启的时候,会使用AOF来重新构建数据库。

RDB文件的创建与载入

有两个Redis命令可以用于生成RDB文件,一个是save,另一个是bgsave
save命令会阻塞redis服务器进程,直到RDB文件创建完毕为止,在服务器进程阻塞期间,服务器不能处理任何命令请求;和save命令直接阻塞服务器进程的做法不同,bgsave命令去派生一个子进程,然后由子进程负责创建RDB文件,服务器进程(父进程)继续处理命令请求。

因为AOF文件的更新频率通常比RDB文件的更新频率高,所以如果服务器开启了AOF持久化功能,那么服务器会优先使用AOF文件来还原数据库状态。只有在AOF持久化功能处于关闭状态时,服务器才会使用RDB文件来还原数据库状态。

RDB文件载入时的服务器状态

服务器在载入RDB文件期间,会一直处于阻塞状态,直到载入工作完成为止。

自动间隔性保存

save 命令由服务器进程执行保存工作,bgsave命令则由子进程执行保存工作,所以save命令会阻塞服务器,而bgsave命令则不会。
因为bgsave命令还可以在不阻塞服务器进程的情况下执行,所以redis允许用户通过设置服务器配置的save选项,让服务器每隔一段时间自动执行一次bgsave命令
用户可以通过save选项设置多个保存条件,但只要其中任意一个条件被满足,服务器就会执行bgsave命令。
举个例子,如果我们向服务器提供以下配置:

save 900 1
save 300 10
save 60 10000

那么只要满足以下三个条件中的任意一个,Bgsave命令就会被执行

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

AOF持久化

除了RDB持久化功能之外,Redis还提供了AOF(Append Only File)持久化功能。与RDB持久化通过保存数据库中的键值对来记录数据库状态不同,AOF持久化是通过保存Redis服务器所执行的写命令来记录数据库状态的。
Redis持久化方式_第1张图片
举个例子,如果我们对空白的数据库执行以下写命令,那么数据库中将包含三个键值对:
Redis持久化方式_第2张图片
RDB持久化保存数据库状态的方法是将msg、fruits、numbers三个键的键值对保存到RDB文件中,而AOF持久化保存数据库状态的方法则是将服务器执行的SET、SADD、RPUSH三个命令保存到AOF文件中。
被写入AOF文件的所有写命令都是以Redis的命令请求协议格式保存的,因为Redis的命令请求协议格式是纯文本格式,所以我们可以直接打开一个AOF文件,观察里面的内容。
在这里插入图片描述
在这个AOF文件里面,除了用于指定数据库的select命令是服务器自动添加的之外,其他都是我们之前通过客户端发送的命令。
服务器在启动时,可以通过载入和执行AOF文件中保存的命令来还原服务器关闭之前的数据库状态,以下就是服务器载入AOF文件并还原数据库状态时打印的日志:
Redis持久化方式_第3张图片

AOF持久化的实现

AOF持久化功能的实现可以分为命令追加、文件写入、文件同步三个步骤。
命令追加:当AOF持久化功能处于打开状态时,服务器在执行完一个写命令之后,会以协议格式将被执行的写命令追加到服务器状态的aof_buf缓冲区的末尾:
Redis持久化方式_第4张图片
举个例子,如果客户端向服务器发送以下命令:
Redis持久化方式_第5张图片
那么服务器在执行这个set命令之后,会将以下协议内容追加到aof_buf缓冲区的末尾:
Redis持久化方式_第6张图片
又例如,如果客户端向服务器发送以下命令:
Redis持久化方式_第7张图片
那么服务器在执行这个RPUSH命令之后,会将以下协议内容追加到aof_buf缓冲区的末尾:
在这里插入图片描述
文件写入与同步:redis的服务器进程就是一个事件循环(loop),这个循环中的文件事件负责接收客户端的命令请求,以及向客户端发送命令回复,而时间事件则负责执行serverCron函数这样需要定时运行的函数。
因为服务器在处理文件事件时可能会执行写命令,使得一些内容被追加到aof_buf缓存区里面,所以在服务器每次结束一个事件循环之前,它都会调用flushAppendOnlyFile函数,考虑是否需要将aof_buf换存区中的内容写入和保存到AOF文件里面,这个过程可以用以下威代码表示:
Redis持久化方式_第8张图片
flushAppendOnlyFile函数的行为由服务器appendfsync选项的值来决定,各个不同值产生的行为如下图:
Redis持久化方式_第9张图片
如果用户没有主动为appendfsync选项设置值,那么appendfsync选项的默认值为everysec。
为了提高文件的写入效率,在现代操作系统中,当用户调用write函数,将一些数据写入到文件的时候,操作系统通常会将写入数据暂时保存在一个内存缓冲区里面,等到缓冲区的空间被填满、或者超过了指定的时限之后,才真正地将缓存区中的数据写入到磁盘里面。
这种做法虽然提高了效率,但也为写入数据带来了安全我呢提,因为如果计算机发生停机,那么保存在内存缓冲区里面写入数据将会丢失。
为了,系统提供了fsync和fdatasync两个同步函数,它们可以强制让操作系统立即将缓存区中的数据写入到磁盘里面,从而确保写入数据的安全性。
举例,假设服务器在处理文件事件期间,执行了以下三个写入命令:
Redis持久化方式_第10张图片
那么aof_buf缓冲区将包含这三个命令的协议内容:
Redis持久化方式_第11张图片
如果这时flushAppendOnlyFile函数被调用,假设服务器当前appendfsync选项的值为everysec,并且距离上次同步AOF文件已经超过一秒钟,那么服务器会先将aof_buf中的内容写入到AOF文件中,然后再对AOF文件进行同步。

AOF持久化的效率和安全性:服务器配置appendfsync选项的值直接决定AOF持久化功能的效率和安全性。

  • 当appendfsync的值为always时,服务器在每个事件循环都要将aof_buf缓存区中的所有内容写入到AOF文件,并且同步AOF文件,所以always的效率是appendfsync选项的三个值当中最慢的一个,但从安全性来说,always也是最安全的,因为即使出现故障停机,AOF持久化也只会丢失一个事件循环中所产生的命令数据
  • 当appendfsync的值为everysec时,服务器在每个事件循环都要将aof_buf缓冲区中的所有内容写入到AOF文件,并且每隔一秒就要在子线程中对AOF文件进行一次同步。从效率上来讲,everysec模式足够快,并且就算出现故障,数据库也只丢失一秒钟的命令数据。
  • 当appendfsync的值为no时,服务器在每个事件循环都要将aof_buf缓存区中的所有内容写入到AOF文件,至于何时对AOF文件进行同步,则由操作系统控制。因为处于no模式下的flushAppendOnlyFile调用无须执行同步操作,所以该模式下的AOF文件写入速度总是最快的,不过因为这种模式会在系统缓存中积累一段时间的写入数据,所以该模式下的单次同步时长通常是三种模式中时间最长的。从平摊操作的角度来看,no模式和everysec模式的效率类似,当出现故障停机时,使用no模式的服务器将丢失上次同步AOF文件之后的所有写命令数据

你可能感兴趣的:(redis,数据库,服务器)