面试必问的 Redis:RDB、AOF、混合持久化( 三 )


 
AOF 的缺点
1)对于相同的数据集,AOF 文件的大小一般会比 RDB 文件大 。
 
2)根据所使用的 fsync 策略,AOF 的速度可能会比 RDB 慢 。通常 fsync 设置为每秒一次就能获得比较高的性能,而关闭 fsync 可以让 AOF 的速度和 RDB 一样快 。
 
3)AOF 在过去曾经发生过这样的 bug :因为个别命令的原因,导致 AOF 文件在重新载入时,无法将数据集恢复成保存时的原样 。(举个例子,阻塞命令 BRPOPLPUSH 就曾经引起过这样的 bug )。虽然这种 bug 在 AOF 文件中并不常见,但是相较而言,RDB 几乎是不可能出现这种 bug 的 。
 
相关源码在 aof.c,核心方法是:feedAppendOnlyFile、flushAppendOnlyFile
 
混合持久化的实现原理、优缺点
 
描述:混合持久化并不是一种全新的持久化方式,而是对已有方式的优化 。混合持久化只发生于 AOF 重写过程 。使用了混合持久化,重写后的新 AOF 文件前半段是 RDB 格式的全量数据,后半段是 AOF 格式的增量数据 。
 
整体格式为:[RDB file][AOF tail]
 
开启:混合持久化的配置参数为 aof-use-rdb-preamble,配置为 yes 时开启混合持久化,在 redis 4 刚引入时,默认是关闭混合持久化的,但是在 redis 5 中默认已经打开了 。
 
关闭:使用 aof-use-rdb-preamble no 配置即可关闭混合持久化 。
 
混合持久化本质是通过 AOF 后台重写(bgrewriteaof 命令)完成的,不同的是当开启混合持久化时,fork 出的子进程先将当前全量数据以 RDB 方式写入新的 AOF 文件,然后再将 AOF 重写缓冲区(aof_rewrite_buf_blocks)的增量命令以 AOF 方式写入到文件,写入完成后通知主进程将新的含有 RDB 格式和 AOF 格式的 AOF 文件替换旧的的 AOF 文件 。
 
优点:结合 RDB 和 AOF 的优点, 更快的重写和恢复 。
 
缺点:AOF 文件里面的 RDB 部分不再是 AOF 格式,可读性差 。
 
相关源码在 aof.c,核心方法是:rewriteAppendOnlyFile
 
为什么需要 AOF 重写
 
AOF 持久化是通过保存被执行的写命令来记录数据库状态的,随着写入命令的不断增加,AOF 文件中的内容会越来越多,文件的体积也会越来越大 。
 
如果不加以控制,体积过大的 AOF 文件可能会对 Redis 服务器、甚至整个宿主机造成影响,并且 AOF 文件的体积越大,使用 AOF 文件来进行数据还原所需的时间就越多 。
 
举个例子,如果你对一个计数器调用了 100 次 INCR,那么仅仅是为了保存这个计数器的当前值,AOF 文件就需要使用 100 条记录 。
 
然而在实际上,只使用一条 SET 命令已经足以保存计数器的当前值了,其余 99 条记录实际上都是多余的 。
 
为了处理这种情况,Redis 引入了 AOF 重写:可以在不打断服务端处理请求的情况下,对 AOF 文件进行重建(rebuild) 。
 
AOF 重写
 
描述:Redis 生成新的 AOF 文件来代替旧 AOF 文件,这个新的 AOF 文件包含重建当前数据集所需的最少命令 。具体过程是遍历所有数据库的所有键,从数据库读取键现在的值,然后用一条命令去记录键值对,代替之前记录这个键值对的多条命令 。
 
命令:有两个 Redis 命令可以用于触发 AOF 重写,一个是 BGREWRITEAOF 、另一个是 REWRITEAOF 命令;
 
开启:AOF 重写由两个参数共同控制,auto-aof-rewrite-percentage 和 auto-aof-rewrite-min-size,同时满足这两个条件,则触发 AOF 后台重写 BGREWRITEAOF 。
// 当前AOF文件比上次重写后的AOF文件大小的增长比例超过100auto-aof-rewrite-percentage 100 // 当前AOF文件的文件大小大于64MBauto-aof-rewrite-min-size 64mb 
关闭:auto-aof-rewrite-percentage 0,指定0的百分比,以禁用自动AOF重写功能 。
auto-aof-rewrite-percentage 0 
REWRITEAOF:进行 AOF 重写,但是会阻塞主进程,服务器将无法处理客户端发来的命令请求,通常不会直接使用该命令 。
 
BGREWRITEAOF:fork 子进程来进行 AOF 重写,阻塞只会发生在 fork 子进程的时候,之后主进程可以正常处理请求 。
 
REWRITEAOF 和 BGREWRITEAOF 的关系与 SAVE 和 BGSAVE 的关系类似 。
 
相关源码在 aof.c,核心方法是:rewriteAppendOnlyFile
 
AOF 后台重写存在的问题
 
AOF 后台重写使用子进程进行从写,解决了主进程阻塞的问题,但是仍然存在另一个问题:子进程在进行 AOF 重写期间,服务器主进程还需要继续处理命令请求,新的命令可能会对现有的数据库状态进行修改,从而使得当前的数据库状态和重写后的 AOF 文件保存的数据库状态不一致 。


推荐阅读