关于java:Redis高级AOF持久化

4次阅读

共计 2744 个字符,预计需要花费 7 分钟才能阅读完成。

1. 介绍

除了 RDB 长久化性能之外,Redis 还提供了 AOF (Append Only File)长久化性能。与 RDB 长久化通过保留数据库中的键值对来记录数据库状态不同,AOF 长久化是通过保留 Redis 服务器所执行的写命令来记录数据库状态的



RDB 长久化保留数据库状态的办法是将 K、V 键值对保留到 RDB 文件中,而 AOF 长久化保留数据库状态的办法则是将服务器执行的 SET、SADD 等命令保留到 AOF 文件中。

被写入 AOF 文件的所有命令都是以 Redis 的命令申请协定格局保留的,因为 Redis 的命令申请协定是纯文本格式

在这个 AOF 文件外面,除了用于指定数据库的 SELECT 命令是服务器主动增加的之外, 其余都是咱们之前通过客户端发送的命令。

 服务器在启动时,能够通过载人和执行 AOF 文件中保留的命令来还原服务器敞开之前的数据库状态,以下就是服务器载入 AOF 文件并还原数据库状态时打印的日志:
 ![image.png](/img/bVcRaSu)

2. AOF 长久化剖析

AOF 长久化性能的实现能够分为命令追加(append)、文件写入、文件同步 (sync) 三个步骤。

(1)命令追加

当 AOF 长久化性能处于关上状态时,服务器在执行完一个写命令之后,会以协定格局将被执行的写命令追加到服务器状态的 aof_buf 缓冲区的开端:

(2)文件写入文件同步

Redis 的服务器过程就是一个事件循环(loop),这个循环中的文件事件负责接管客户端的命令申请,以及向客户端发送命令回复,而工夫事件则负责执行像 serverCron 函数这样须要定时运行的函数。
因为服务器在解决文件事件时可能会执行写命令,使得一些内容被追加到 aof_buf 缓冲区外面,所以在服务器每次完结一个事件循环之前,它都会调用 flushAppendOnlyFile 函数,思考是否须要将 aof_buf 缓冲区中的内容写入和保留到 AOF 文件外面
flushAppendOnlyFile 函数的行为由服务器配置的 appendfsync 选项的值来决。

如果用户没有被动为 appendfsync 选项设置值,那么 appendfsync 选项的默认值为 everysec,对于 appendfsync 选项的更多信息,请参考 Redis 我的项目附带的示例配置文件 redis.conf。


appendfsync,如果 appendfsync 配置成 everysec,AOF 每秒落盘一次,不过这种配置形式有可能会失落 1 秒的数据。如果 appendfsync 配置成 always,每次操作申请的记录都落盘后再返回胜利信息给客户端。

4. AOF 文件的载入与数据还原

因为 AOF 文件外面蕴含了重建数据库状态所需的所有写命令,所以服务器只有读入并从新执行一遍 AOF 文件外面保留的写命令,就能够还原服务器敞开之前的数据库状态。

5. AOF 重写

(1)介绍

因为 AOF 长久化是通过保留被执行的写命令来记录数据库状态的,所以随着服务器运行工夫的流逝,AOF 文件中的内容会越来越多,文件的体积也会越来越大,如果不加以控制的话,体积过大的 AOF 文件很可能对 Redis 服务器、甚至整个宿主计算机造成影响,并且 AOF 文件的体积越大,应用 AOF 文件来进行数据还原所需的工夫就越多。
为了解决 AOF 文件体积收缩的问题,Redis 提供了 AOF 文件重写(rewrite)性能。通过该性能,Redis 服务器能够创立一个新的 AOF 文件来代替现有的 AOF 文件,新旧两个 AOF 文件所保留的数据库状态雷同,但新 AOF 文件不会蕴含任何节约空间的冗余命令,所以新 AOF 文件的体积通常会比旧 AOF 文件的体积要小得多。

(2)原理

AOF 文件重写并不需要对现有的 AOF 文件进行任何读取、剖析或者写入操作,这个性能是通过读取服务器以后的数据库状态来实现的。

如上图所示,我执行了四次 set 命令,而后 AOF 本来形式须要生成四条记录,然而其实咱们只须要执行最新的命令即可,而不须要四条命令,即只须要获取最新的状态。

所有类型的键都能够用同样的办法去缩小 AOF 文件中的命令数量。首先从数据库中读取键当初的值,而后用一条命令去记录键值对,代替之前记录这个键值对的多条命令,这就是 AOF 重写性能的实现原理。
Redis 源码中 aof_rewrite 函数生成的新 AOF 文件只蕴含还原以后数据库状态所必须的命令,所以新 AOF 文件不会节约任何硬盘空间。
根本的代码流程:
1:开始执行重写操作
2:遍历所有的 KEY
3:疏忽已过期的 KEY
4:依据 KEY 的类型进行命令构建写入到新的 AOF 文件中,如果有过期工夫也须要写入

(3)AOF 后盾重写

下面介绍的 AOF 重写程序 aof_rewrite 函数能够很好地实现创立一个新 AOF 文件的工作,然而,因为这个函数会进行大量的写入操作,所以调用这个函数的线程将被长时间阻塞, 因为 Redis 服务器应用单个线程来解决命令申请,所以如果由服务器间接调用 aof_rewrite 函数的话,那么在重写 AOF 文件期间,服务器将无奈解决客户端发来的命令申请。所以 Redis 反对将 AOF 重写放在子线程中执行。

 不过,应用子过程也有一个问题须要解决, 因为子过程在进行 AOF 重写期间,服务器过程还须要持续解决命令申请,而新的命令可能会对现有的数据库状态进行批改,从而使得服务器以后的数据库状态和重写后的 AOF 文件所保留的数据库状态不统一

为了解决这种数据不统一问题,Redis 服务器设置了一个 AOF 重写缓冲区,这个缓冲区在服务器创立子过程之后开始应用,当 Redis 服务器执行完一个写命令之后它会同时将这个写命令发送给 AOF 缓冲区和 AOF 重写缓冲区。

【根本流程】
1:执行客户端发来的写入命令
2:将执行后的写命令追加到 AOF 缓冲区中
3:将执行后的写命令追加到 AOF 重写缓冲区中

这样一来能够保障:
AOF 缓冲区的内容会定期被写入和同步到 AOF 文件,对现有 AOF 文件的解决工作会如常进行。
从创立子过程开始,服务器执行的所有写命令都会被记录到 AOF 重写缓冲区外面。当子过程实现 AOF 重写工作之后,它会向父过程发送一个信号,父过程在接到该信号之后,会调用一个信号处理函数,并执行以下工作:

1:将 AOF 重写缓冲区中的所有内容写入到新 AOF 文件中,这时新 AOF 文件所保留的数据库状态将和服务器以后的数据库状态统一。

2:对新的 AOF 文件进行改名,原子地(atomic)笼罩现有的 AOF 文件,实现新旧两个 AOF 文件的替换。

这个信号处理函数执行结束之后,父过程就能够持续像平常一样接受命令申请了。在整个 AOF 后盾重写过程中,只有信号处理函数执行时会对服务器过程(父过程)造成阻塞,在其余时候,AOF 后盾重写都不会阻塞父过程,这将 AOF 重写对服务器性能造成的影响降到了最低。

本文由博客群发一文多发等经营工具平台 OpenWrite 公布

正文完
 0