Redis RDB 与 AOF 的区别

Redis 主要作为数据缓存,缓存的目标主要是那些需要经常访问的数据,或计算复杂而耗时的数据。缓存的效果就是减少了数据库读的次数,减少了复杂数据的计算次数,从而减少请求响应的时间。

[TOC]

Redis 持久化

  • Redis 提供了两种持久化的方式,分别是 RDB(Redis DataBase)和 AOF(Append Only File)。

  • RDB,是在不同的时间点,将 Redis 存储的数据生成快照并存储到磁盘等介质上。

  • AOF,是将 Redis 执行过的所有写指令记录下来,在下次 Redis 重新启动时,只要把这些写指令从前到后重复执行一遍,就可以实现数据恢复。

  • RDB 和 AOF 两种方式可以同时使用,在这种情况下,如果 Redis 重启的话,则会优先采用 AOF 方式来进行数据恢复,这是因为 AOF 方式的数据恢复完整度更高。

  • 如果没有数据持久化的需求,可以关闭 RDB 和 AOF。这样的话,Redis 将变成一个纯内存数据库,就像 memcache 一样。

RDB

  • RDB 方式,是将 Redis 某一时刻的数据持久化到磁盘中,是一种快照式的持久化方法。

  • Redis 在进行数据持久化的过程中,会先将数据写入到一个临时文件中,待持久化过程都结束了,才会用这个临时文件替换上次持久化好的文件。正是这种特性,让我们可以随时来进行备份,因为快照文件总是完整可用的。

  • 对于 RDB 方式,Redis 会单独创建(Fork)一个子进程来进行持久化,而主进程是不会进行任何 IO 操作的,这样就确保了 Redis 极高的性能。

  • 如果需要进行大规模数据的恢复,且对于数据恢复的完整性不是非常敏感,那 RDB 方式要比 AOF 方式更加的高效。

  • 虽然 RDB 有不少优点,但它的缺点也是不容忽视的。如果你对数据的完整性非常敏感,那么 RDB 方式就不太适合你,因为即使你每 5 分钟都持久化一次,当 Redis 故障时,仍然会有近 5 分钟的数据丢失。

AOF

  • AOF,英文是 Append Only File,即只允许追加不允许修改的文件。

  • AOF 方式是将执行过的写指令记录下来,在数据恢复时按照从前到后的顺序再将指令都执行一遍。

  • 我们通过配置 Redis.conf 中的 appendonly yes 就可以打开 AOF 功能。如果有写操作(如 SET 等),操作就会被追加到 AOF 文件的末尾。

  • 默认的 AOF 持久化策略是每秒钟 fsync 一次(fsync 是指把缓存中的写指令记录到磁盘中),因为在这种情况下,Redis 仍然可以保持很好的处理性能,即使 Redis 故障,也只会丢失最近 1 秒钟的数据。

  • 如果在追加日志时,恰好遇到磁盘空间满、inode 满或断电等情况导致日志写入不完整,也没有关系,Redis 提供了 Redis-check-aof 工具,可以用来进行日志修复。

  • 因为采用了追加方式,如果不做任何处理的话,AOF 文件会变得越来越大,为此,Redis 提供了 AOF 文件重写(rewrite)机制,即当 AOF 文件的大小超过所设定的阈值时,Redis 就会启动 AOF 文件的内容压缩,只保留可以恢复数据的最小指令集。举个例子或许更形象,假如我们调用了 100 次 INCR 指令,在 AOF 文件中就要存储 100 条指令,但这明显是很低效的,完全可以把这 100 条指令合并成一条 SET 指令,这就是重写机制的原理。

  • 在进行 AOF 重写时,仍然是采用先写临时文件,全部完成后再替换的流程,所以断电、磁盘满等问题都不会影响 AOF 文件的可用性。

  • AOF 方式的另一个好处,我们通过一个 “场景再现” 来说明,某同学在操作 Redis 时,不小心执行了 FLUSHALL,导致 Redis 内存中的数据全部被清空了,只要 Redis 配置了 AOF 持久化方式,且 AOF 文件还没有被重写(rewrite),就可以用最快的速度暂停 Redis 并编辑 AOF 文件,将最后一行的 FLUSHALL 命令删除,然后重启 Redis,就可以恢复 Redis 的所有数据到 FLUSHALL 之前的状态了,但是如果 AOF 文件已经被重写了,就无法通过这种方法来恢复数据了。

  • AOF 方式也同样存在缺陷,比如在同样数据规模的情况下,AOF 文件要比 RDB 文件的体积大。而且,AOF 方式的恢复速度也要慢于 RDB 方式。

  • 如果你直接执行 BGREWRITEAOF 命令,那么 Redis 会生成一个全新的 AOF 文件,其中便包括了可以恢复现有数据的最少的命令集。

  • 如果运气比较差,AOF 文件出现了被写坏的情况,也不必过分担忧,Redis 并不会贸然加载这个有问题的 AOF 文件,而是报错退出。这时可以通过以下步骤来修复出错的文件:

    1. 备份被写坏的 AOF 文件

    2. 运行 Redis-check-aof–fix 进行修复

    3. diff -u 来看下两个文件的差异,确认问题点

    4. 重启 Redis,加载修复后的 AOF 文件

AOF 重写

  1. 在重写即将开始之际,Redis 会创建(fork)一个 “重写子进程”,这个子进程会首先读取现有的 AOF 文件,并将其包含的指令进行分析压缩并写入到一个临时文件中。

  2. 与此同时,主工作进程会将新接收到的写指令一边累积到内存缓冲区中,一边继续写入到原有的 AOF 文件中,这样做是保证原有的 AOF 文件的可用性,避免在重写过程中出现意外。

  3. 当 “重写子进程” 完成重写工作后,它会给父进程发一个信号,父进程收到信号后就会将内存中缓存的写指令追加到新 AOF 文件中。

  4. 当追加结束后,Redis 就会用新 AOF 文件来代替旧 AOF 文件,之后再有新的写指令,就都会追加到新的 AOF 文件中了。

如何选择 RDB 和 AOF

  1. 对于 RDB 还是 AOF,官方的建议是两个同时使用。这样可以提供更可靠的持久化方案。

  2. Redis 的备份和还原,可以借助第三方的工具 Redis-dump。

Redis 的两种持久化方式的缺点

  1. RDB 需要定时持久化,风险是可能会丢两次持久之间的数据,量可能很大。

  2. AOF 每秒 fsync 一次指令硬盘,如果硬盘 IO 慢,会阻塞父进程;风险是会丢失 1 秒多的数据

  3. AOF 在 Rewrite 过程中,主进程把指令存到 mem-buffer 中,最后写盘时会阻塞主进程。

Redis持久化----RDB和AOF 的区别

Last updated

Was this helpful?