你对Redis持久化了解多少?一篇文章让你明白Redis持久化

Redis 一共有 2 种持久化方式,分别是 RDB 和 AOF,下面我来详细介绍两种方式在各个过程所做的事情,特点等等。

1. RDB 持久化

RDB 持久化是 Redis 默认的持久化方式。

它所生成的 RDB 文件是一个压缩的二进制文件,通过该文件可以还原生成 RDB 文件时的数据库状态

PS:数据库状态是指 Redis 服务器的非空数据库以及他们键值对的统称

1.1 RDB 文件的创建

有两个命令可以生成 RDB 文件,一个是 SAVE、另一个是 BGSAVE。

两者的区别在于:前者会阻塞 Redis 服务器进程,直到 RDB 文件创建完毕为止。

而在服务器进程阻塞期间,服务器是不能处理任何命令请求的。

后者则不会阻塞服务器进程,因为是通过 fork 一个子进程,并让其去创建 RDB 文件,而服务器进程(父进程)继续则继续处理命令请求。

当写完数据库状态后,新 RDB 文件就会原子地替换旧的 RDB 文件。

此处小提问:如果在执行 BGSAVE 期间,客户端发送 SAVE、BGSAVE 或 BGREWRITEAOF 命令给服务端,服务端会如何处理呢?

 

答案:在执行 BGSAVE 期间,上述三个命令都不会被执行。 详细原因:前两个会被直接拒绝,原因是为了避免父子进程同时执行两个 rdbSave 调用,防止产生竞争条件。 而 BGREWRITEAOF 命令则是会被延迟到 BGSAVE 命令执行之后再执行。 但如果是 BGREWRITEAOF 命令正在执行,此时客户端发送 BGSAVE 命令则会被拒绝。 因为 BGREWRITEAOF 和 BGSAVE 都是由子进程执行的,所以在操作方面没有冲突的地方,不能同时执行的原因是性能上的考虑——并发出两个子进程,并且这两个子进程都会同时执行大量 io(磁盘写入)操作

 

1.2 RDB 文件的载入

RDB 文件的载入是在服务器启动时自动执行的,所以没有用于载入的命令,期间阻塞主进程。

只要没有开启 AOF 持久化功能,在启动时检测到有 RDB 文件,就会自动载入。

当服务器有开启 AOF 持久化功能时,服务器将会优先使用 AOF 文件来还原数据库状态。原因是 AOF 文件的更新频率通常比 RDB 文件的更新频率高。

1.3 自动间隔性保存

对于 RDB 持久化而言,我们一般都会使用 BGSAVE 来持久化,毕竟它不会阻塞服务器进程。

在 Redis 的配置文件,有提供设置服务器每隔多久时间来执行 BGSAVE 命令。

Redis 默认是如下配置:

save 900 1 // 900 秒内,对数据库至少修改 1 次。下面同理

save 300 10

save 60 10000

只要满足其中一种情况,服务器就会执行 BGSAVE 命令。

2. AOF 持久化

我们从上面的介绍知道,RDB 持久化通过保存数据库状态来持久化。而 AOF 与之不同,它是通过保存对数据库的写命令来记录数据库状态。

比如执行了 set key 123,Redis 就会将这条写命令保存到 AOF 文件中。

在服务器下次启动时,就可以通过载入和执行 AOF 文件中保存的命令,来还原服务器关闭前的数据库状态了。

总体流程和 RDB 持久化一样 —— 都是创建一个 xxx 文件、在服务器下次启动时就载入这个文件来还原数据

那么,AOF 持久化具体是怎么实现的呢?

2.1 AOF 持久化实现

 

AOF 持久化功能的实现可以分为 3 个步骤:命令追加、文件写入、文件同步

其中命令追加很好理解,就是将写命令追加到 AOF 缓冲区的末尾。

那文件写入和文件同步怎么理解呢?刚开始我也一脸懵逼,终于在网上找到了答案,参考见文末,有兴趣的读者可以去看看。

先不卖关子了,简单一句话解释就是:前者是缓冲区内容写到 AOF 文件,后者是将 AOF 文件保存到磁盘。

ok,明白什么意思之后,我们稍微详细看下这两个东西是什么鬼。

在《Redis设计与实现》中提到,Redis 服务器进程就是一个事件循环,这个循环中的文件事件(socket 的可读可写事件)负责接收客户端的命令请求,以及向客户端发送命令结果。

因为服务器在处理文件事件时,可能会发生写操作,使得一些内容会被追加到 AOF 缓冲区末尾。所以,在服务器每次结束一个事件循环之前 ,都会调用 flushAppendOnlyFile 方法。

这个方法执行以下两个工作:

WRITE:根据条件,将缓冲区内容写入到 AOF 文件。

SAVE:根据条件,调用 fsync 或 fdatasync 函数,将 AOF 文件保存到磁盘中。

 

两个步骤都需要根据一定的条件来执行,而这些条件由 Redis 配置文件中的 appendfsync 选项来决定的,一共有三个选择:

1. appendfsync always:每执行一个命令保存一次

2. appendfsync everysec(默认,推荐):每一秒钟保存一次

3. appendfsync no:不保存

下面说下三个的区别:

appendfsync always:每次执行完一个命令之后, WRITE 和 SAVE 都会被执行

appendfsync everysec:SAVE 原则上每隔一秒钟就会执行一次。

appendfsync no:每次执行完一个命令之后, WRITE 会执行,SAVE 都会被忽略,只会在以下任意一种情况中被执行:

Redis 被关闭

AOF 功能被关闭

系统的写缓存被刷新(可能是缓存已经被写满,或者定期保存操作被执行。完成依赖 OS 的写入,一般为 30 秒左右一次)

 

而对于操作特性来分析的话,则是如下情况:

 

你对Redis持久化了解多少?一篇文章让你明白Redis持久化

内容版权声明:除非注明,否则皆为本站原创文章。

转载注明出处:https://www.heiqu.com/zyjxjw.html