一、RDB持久化的缺点
创建RDB文件需要将服务器所有的数据库的数据都保存起来,这是一个非常耗费资源和时间的操作,所以服务器需要隔一段时间才能创建一个新的RDB文件,就也是说创建RDB文件的操作不能执行的过于频繁,否则就会严重地影响服务器的性能。
在 save 配置选项的默认设置下,即使有超过 10000 次修改操作发生,服务器也至少会间隔一分钟才创建下一个 RDB 文件:
save 900 1 save 300 10 save 60 10000
如果在等待创建下一个 RDB 文件的过程中,服务器遭遇了意外停机,那么用户将丢失最后一次创建RDB 文件之后,数据库发生的所有修改。
解决方法:
为了解决 RDB 持久化在遭遇意外停机时丢失大量数据的问题,Redis 提供了 AOF 持久化功能。比起 RDB 持久化, AOF 持久化有一个巨大的优势,那就是,用户可以根据自己的需要对 AOF 持久化进行调整,让 Redis 在遭遇意外停机时不丢失任何数据,或者只丢失一秒钟数据,这比 RDB 持久化遭遇意外停机时,丢失的数据要少得多。
二、AOF 持久化的运作原理
数据保存
AOF 持久化保存数据库数据的方法是:每当有修改数据库的命令被执行时,服务器就会将被执行的命令写入到 AOF 文件的末尾。
数据还原
因为 AOF 文件里面储存了服务器执行过的所有数据库修改命令,所以给定一个 AOF 文件,服务器只要重新执行一遍 AOF 文件里面包含的所有命令,就可以达到还原数据库数据的目的。
举个例子,对于包含以下内容的 AOF 文件来说:
SELECT 0 SET msg "hello" INCR counter SADD alphabets "a" "b" "c" INCR counter
服务器只要重新执行这些命令,就可以还原出右图所示的数据库
安全性问题
虽然服务器每执行一个修改数据库的命令,就会将被执行的命令写入到 AOF 文件,但这并不意味着AOF 持久化不会丢失任何数据。
在目前常见的操作系统中,执行系统调用 write 函数,将一些内容写入到某个文件里面时,为了提高效率,系统通常不会直接将内容写入到硬盘里面,而是先将内容放入到一个内存缓冲区(buffer)里面,等到缓冲区被填满,或者用户执行 fsync 调用和 fdatasync 调用时,才将储存在缓冲区里面的内容真正地写入到硬盘里面。
对于 AOF 持久化来说,当一条命令真正地被写入到硬盘里面时,这条命令才不会因为停机而意外丢失。
因此,AOF 持久化在遭遇停机时丢失命令的数量,取决于命令被写入到硬盘的时间:
1) 越早将命令写入到硬盘,发生意外停机时丢失的数据就越少;
2) 越迟将命令写入到硬盘,发生意外停机时丢失的数据就越多。
安全性控制
为了控制 Redis 服务器在遇到意外停机时丢失的数据量,Redis 为 AOF 持久化提供了 appendfsync选项,这个选项的值可以是 always 、 everysec 或者 no ,这些值的意思分别为:
always :服务器每写入一个命令,就调用一次 fdatasync ,将缓冲区里面的命令写入到硬盘里面。在这种模式下,服务器即使遭遇意外停机,也不会丢失任何已经成功执行的命令数据。
everysec :服务器每秒钟调用一次 fdatasync ,将缓冲区里面的命令写入到硬盘里面。在这种模式下,服务器遭遇意外停机时,最多只丢失一秒钟内执行的命令数据。
no :服务器不主动调用 fdatasync ,由操作系统决定何时将缓冲区里面的命令写入到硬盘里面。在这种模式下,服务器遭遇意外停机时,丢失命令的数量是不确定的。
运行速度: always 的速度慢, everysec 和 no 都很快。默认值: everysec 。
三、AOF 重写
随着服务器的不断运行,为了记录数据库发生的变化,服务器会将越来越多的命令写入到 AOF 文件里面,使得 AOF 文件的体积不断地增大。为了让 AOF 文件的大小控制在合理的范围,避免它胡乱地增长,Redis 提供了 AOF 重写功能,通过这个功能,服务器可以产生一个新的 AOF 文件:
1) 新 AOF 文件记录的数据库数据和原有 AOF 文件记录的数据库数据完全一样;
2) 新的 AOF 文件会使用尽可能少的命令来记录数据库数据,因此新 AOF 文件的体积通常会比原有 AOF 文件的体积要小得多。
3) AOF 重写期间,服务器不会被阻塞,可以正常处理客户端发送的命令请求。
AOF 重写的触发
有两种方法可以触发 AOF 重写:
1) 客户端向服务器发送 BGREWRITEAOF 命令;
2) 通过设置配置选项来让服务器自动执行 BGREWRITEAOF 命令,它们分别是:
auto-aof-rewrite-min-size <size> ,触发 AOF 重写所需的最小体积:只有在 AOF 文件的体积
大于等于 size 时,服务器才会考虑是否需要进行 AOF 重写。这个选项用于避免对体积过小的AOF 文件进行重写。
auto-aof-rewrite-percentage <percent> ,指定触发重写所需的 AOF 文件体积百分比:当 AOF
文件的体积大于 auto-aof-rewrite-min-size 指定的体积,并且超过上一次重写之后的 AOF 文件体积的 percent% 时,就会触发 AOF 重写。(如果服务器刚刚启动不久,还没有进行过 AOF 重写,那么使用服务器启动时载入的 AOF 文件的体积来作为基准值。)将这个值设置为 0 表示关闭自动 AOF 重写。
例子:
auto-aof-rewrite-percentage 100 auto-aof-rewrite-min-size 64mb
四、AOF持久化小结
创建 RDB 文件需要将服务器包含的所有数据全部写入到硬盘里面,这是一个非常耗费资源和时间的操作,因此服务器通常需要每隔一段时间才创建一个新的 RDB 文件,这使得服务器在遭遇意外停机时,可能会丢失大量数据;
AOF 持久化会将每个修改了数据库的命令都写入到 AOF 文件末尾,在启动服务器的时候,只要重新执行 AOF 文件包含的命令,就可以还原服务器原有的数据库数据;
因为写入缓冲区的存在,AOF 持久化的安全性取决于缓冲区里面的命令何时会被真正地写入到硬盘里面,通过设置 appendfsync 配置选项,用户可以让 AOF 持久化不丢失任何已经成功执行的命令数据,或者只丢失一秒钟内被执行的命令数据,又或者不主动执行 fdatasync 调用,将写入硬盘的时机交给操作系统来管理;
随着服务器的运行,AOF 文件会产生越来越多冗余命令,使得文件的体积不断增大,而通过执行 AOF重写操作,服务器可以创建一个保存相同数据库数据,但不包含任何冗余命令的新 AOF 文件,并使用这个新 AOF 文件来代替原有的 AOF 文件。
五、RDB和AOF对比
可以同时使用两种持久化,根据你的需求来判断。还原数据优先使用 AOF 文件。