作为程序员你不知道 Redis 持久化,如何通过面试?

我们都知道 Redis 是个内存数据库,所有的数据都存储在内存中。一旦服务器上 Redis 进程退出,数据库中的数据就会丢失。持久化是做什么事呢?持久化简单的理解就是将内存中的数据做个备份。Redis 的持久化有两种方法,即 RDB 持久化和 AOF 持久化。本文将会分两部分介绍这两种持久化方法,以及实现原理。

作为程序员你不知道 Redis 持久化,如何通过面试?

01RDB 持久化

Redis 数据持久化是将内存中的数据保存到磁盘里,避免数据意外丢失。RDB 持久化会生成一个 RDB 文件,这个 RDB 文件是一个经过压缩的二进制文件。通过该文件可以还原出 Redis 数据库中的数据。RDB 的持久化可以手动执行,也可以根据服务器配置项定期自动执行。

下面我们一起学习一下 RDB 文件是怎么创建的。有两个命令可以创建 RDB 文件,一个是 SAVE,另一个是 BGSAVE。

作为程序员你不知道 Redis 持久化,如何通过面试?

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

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

SAVE 命令和 BGSAVE 命令的底层调用的函数都是同一个函数 rdbSave,只不过 SAVE 命令是直接调用这个函数,而 BGSAVE 会 fork () 出子进程来调用这个函数。伪代码如下:

作为程序员你不知道 Redis 持久化,如何通过面试?

RDB 文件的载入工作是在服务器启动时自动执行的,只要 Redis 服务器在启动时检测到 RDB 文件存在,就会自动载入 RDB 文件。值得一提的是,Redis 服务器在载入 RDB 文件的期间,会一直处于阻塞状态,直到载入工作完成为止。

BGSAVE 命令在不阻塞服务器进程的情况下执行,所以 Redis 允许用户通过设置服务器的 save 选项来让服务器每隔一段时间自动执行一次 BGSAVE 命令。

作为程序员你不知道 Redis 持久化,如何通过面试?

上面条件只要满足其中一个,BGSAVE 命令就会被执行:

第一条的意思是:服务器在 900 秒内对数据库执行过至少 1 次修改,就会执行 BGSAVE 命令第二条的意思是:服务器在 300 秒内对数据库执行过至少 10 次修改,就会执行 BGSAVE 命令第三条的意思是:服务器在 60 秒内对数据库执行过至少 10000 次修改,就会执行 BGSAVE 命令

02AOF 持久化

除了 RDB 持久化之外,Redis 还提供了 AOF 持久化功能,两者的实现方式有着很大的不同。RDB 持久化是通过保存数据库中的键值对来记录数据库状态,而 AOF 持久化是通过保存 Redis 服务器所执行的写命令来记录记录数据库状态。

AOF 持久化是如何实现的呢?AOF 持久化分文三个步骤:命令追加、文件写入、文件同步。

命令追加:当 AOF 持久化功能打开时,服务器在执行完一个写命令后,会以一定的格式将被执行的写命令追加到服务器中的 aof 缓冲区中。aof 缓冲区是 redisServer 结构体维护的一个 SDS 结构的属性。文件写入:文件写入是指从 Redis 的 aof 缓冲区写入到操作系统的内存缓冲区。这个过程是为了提高文件的写入效率,但是带来的风险是服务器出现故障时,内存缓冲区中的数据会丢失掉。文件同步:这个过程是将内存缓冲区中的数据写入到硬盘中的 AOF 文件中

Redis 中默认执行的是 RDB 持久化,如何打开 AOF 持久化呢?我们先来看看 AOF 的配置项:

appendonly:这个参数是 AOF 的开关,配置成 yes 可以打开 AOF 持久化机制。打开 AOF 机制后 appendfsync:我们知道 Redis 中有个事件循环,Redis 在每个事件循环都会将 aof 缓冲区中的内容写入到操作系统的内存缓冲区。这个参数就是来配置将内存缓冲区中的数据同步到硬盘上的 AOF 文件中的更新频率,有 always、everysec、no 三个配置值。always 表示每次执行写入操作,就会立即将内存缓冲区中的内容同步到磁盘中的 AOF 文件中。这种配置性能比较差,但是可以确保数据不丢失。everysec 表示每秒执行一次将操作系统的内存缓冲区中的数据同步到磁盘的 AOF 文件中,这个操作由一个线程来负责,性能很高。no 表示由操作系统来控制何时将内存缓冲区中的数据同步到硬盘的 AOF 文件中。这种操作在服务器出现异常时会丢失一部分数据。

下面说说 AOF 文件的还原过程,我们知道 AOF 文件中存储的是所有曾经执行过的写命令,所以服务器只要读入并重新执行一遍 AOF 文件里保存的写命令,就可以还原服务器关闭之前的数据库内容。同时为了解决在 Redis 运行过程中 AOF 文件越来越大,Redis 还提供了 AOF 重写功能,关于 AOF 重写原理在此不具体介绍,有兴趣的我们可以私下讨论。

03RDB 和 AOF 区别和联系,以及同时工作时的情况

首先我们总结一下两种方式的区别和联系:

RDB 持久化:默认开启;全量备份,一次性保存整个数据库;体积小,数据恢复快;服务器异常时可能会丢失部分数据;SAVE 操作会阻塞,BGSAVE 不阻塞 AOF 持久化:默认关闭;增量备份,一次保存一个修改数据库的命令;体积大,数据恢复慢;备份频率可以自己设置;不会出现阻塞当 RDB 和 AOF 同时开始时:

如果 RDB 在执行 snapshotting 操作,那么 redis 不会执行 AOF rewrite; 如果 redis 在执行 AOF rewrite,那么就不会执行 RDB snapshotting 如果 RDB 在执行 snapshotting,此时用户执行 BGREWRITEAOF 命令,那么等 RDB 快照生成之后,才会去执行 AOF rewrite 同时有 RDB snapshot 文件和 AOF 日志文件,那么 redis 重启的时候,会优先使用 AOF 进行数据恢复,因为其中的日志更完整

可以对照附件研究学习,有遇到不懂不明白之处可以在下方留言

GIT 项目推荐:包含多端免授权可商用

发表评论

相关文章