Redis持久化

Redis是内存数据库,如果不将内存中的数据库状态保存到磁盘,那么一旦服务器进程退出,服务器中的数据库状态也会消失。所以Redis提供了持久化功能!

1、RDB(Redis DataBase)机制

  • RDB持久化是指在指定的时间间隔内将内存中的数据集快照写入磁盘。也是默认的持久化方式,这种方式是就是将内存中数据以快照的方式写入到二进制文件中,默认的文件名为dump.rdb(配置文件的dbfilename中配置)。它恢复时是将快照文件直接读到内存里。

  • Redis会单独创建(fork)一个子进程来进行持久化,会先将数据写入到一个临时文件中,待持久化过程都结束了,再用这个临时文件替换上次持久化好的文件。整个过程中,主进程是不进行任何IO操作的,这就确保了极高的性能。如果需要进行大规模数据的恢复,且对于数据恢复的完整性不是非常敏感,那RDB方式要比AOF方式更加的高效。RDB的缺点是最后一次持久化后的数据可能丢失。

  • 触发机制如下(触发后生成一个dump.rdb文件):

    • 配置文件中save规则满足自动触发,实现方式是bgsave。
    • 执行命令save或bgsave会触发。执行save就是中断状态来实现的,而bgsave则是fork子进程来实现,不会中断当前进程执行。
    • 执行flushall、shutdown命令后会触发,实现方式是save。
  • 恢复数据则只需要将dump.rdb文件放在redis启动目录即可。

RDB优点

  • 执行效率高,适用于大规模数据的备份恢复,且自动备份不会影响主线程工作。   
  • 备份的文件占用空间小。其备份的是数据快照,相对于AOF来说文件大小要小一些。

  

RDB缺点

  • 可能会造成部分数据丢失。因为是自动备份,所以如果修改的数据量不足以触发自动备份,同时发生断电等异常导致redis不能正常关闭,所以也没有触发关闭的备份,那么在上一次备份到异常宕机过程中发生的写操作就会丢失。
  • 自动备份通过fork进程来执行备份操作,而fork进程会将当前进程的内存数据完整的复制一份,所以这个过程占用的空间是原来的2倍,可能会导致内存不足。

2、AOF(Append Only File)机制

  • AOF会保存服务器执行的所有写操作到日志文件中,在服务重启以后,会执行这些命令来恢复数据。

  • 日志文件默认为appendonly.aof,Redis以Redis协议格式将命令保存至aof日志文件末尾。

  • AOF默认不开启,需要在redis.conf中开启(appendonly yes)。

  • 使用AOF恢复数据默认情况下只需要将备份文件放在启动目录下然后在启动目录下启动服务器即可。

  • 如果AOF文件有错误,会导致Redis无法启动,此时需要执行redis-check-aof --fix appendonly.aof来修复文件。

  • 为了解决appendonly.aof文件过大的问题,redis提供了一种机制,叫bgrewriteaof。这个命令的作用就是fork()出一个子进程来对appendonly.aof文件进行重写。这个重写操作在redis4.0以前和4.0以后有不同的实现方式。

    • Redis4.0以前的重写主要有两点:删除抵消的命令合并重复的命令。对于set key value和del key这样相互抵消的命令会被直接删除。对于set key value1和set key value2这样重复的命令会进行合并。这样一通操作之后,AOF文件可能会变得很小。
    • Redis4.0之后,开启了RDB和AOF的混合模式。也就是将已有的数据以RDB的方式记录在appendonly.aof文件的头部,对于之后的增量数据以AOF的方式继续追加在appendonly.aof文件中,也就是appendonly.aof文件前半段是快照数据,后半段是redis指令。这样的混合模式结合了RDB和AOF的优点,既能最大限度的减少数据丢失,又能在Redis重启后迅速恢复数据。
    • 重写的触发方式?
      • 手动执行bgrewriteaof进行触发。
      • auto-aof-rewrite-min-size参数设置成64mb,意思是redis尚未执行过bgrewriteaof(从启动开始算),AOF文件需要达到64mb才会第一次执行bgrewriteaof(此后不会再使用auto-aof-rewrite-min-size参数),redis会记录每次执行bgrewriteaof之后,AOF文件的大小。
      • auto-aof-rewrite-percentage设置成100,表示当前的AOF文件大小超过上一次bgrewriteaof后AOF文件的百分比后触发bgrewriteaof。如果上次bgrewriteaof后,AOF为200mb,现在需要AOF文件达到400mb才会执行bgrewriteaof。auto-aof-rewrite-percentage设置成0,表示禁用bgrewriteaof。auto-aof-rewrite-min-size参数的作用就是在AOF文件比较小的时候,防止因为增长过快而频繁调用bgrewriteaof。

AOF优点

  • AOF可以更好的保护数据不丢失。默认会每隔1秒,通过一个后台线程执行一次fsync操作,所以最多丢失1秒钟的数据。
  • AOF文件是一个只进行追加操作的日志文件,因此对AOF文件的写入不需要进行seek。即使日志因为某些原因(比如写入时磁盘已满,写入中途停机),而包含了未写入完整的命令,redis-check-aof工具也可以轻易地修复这种问题。
  • 当AOF文件体积变得过大时,自动地在后台对AOF进行重写。重写后的新AOF文件包含了恢复当前数据集所需的最小命令集合。 整个重写操作是绝对安全的。

AOF缺点

  • 对于同一份数据来说,AOF日志文件通常比RDB数据快照文件更大,恢复速度慢。
  • AOF可能会有bug,就是通过AOF记录的日志,进行数据恢复的时候,没有恢复一模一样的数据出来。

3、总结

两种持久化机制对比

  • RDB持久化方式能够在指定的时间间隔内对你的数据进行快照存储。
  • AOF持久化方式记录每次对服务器写的操作,当服务器重启的时候会重新执行这些命令来恢复原始的数据,AOF命令以Redis协议追加保存每次写的操作到文件未尾,Redis还能对AOF文件进行后台重写,使得AOF文件的体积不至于过大。

同时开启两种持久化机制

  • 在这种情况下,当redis重启的时候会优先载入AOF文件来恢复原始的数据,因为在通常情况下AOF文件保存的数据集要比RDB文件保存的数据集要完整。
  • RDB的数据不实时,同时使用两者时服务器重启也只会找AOF文件,但建议不要只使用AOF,因为RDB更适合用于备份数据库(AOF在不断变化不好备份),快速重启,而且不会有AOF可能潜在的Bug,留着作为一个万一的手段。

性能建议

  • 因为RDB文件只用作后备用途,建议只在Slave上持久化RDB文件,而且只要15分钟备份一次就够了,只保留save 900 1这条规则。
  • 如果Enable AOF,好处是在最恶劣情况下也只会丢失不超过两秒数据,启动脚本较简单只load自己的AOF文件就可以了,代价一是带来了持续的IO,二是AOF rewrite的最后将rewrite过程中产生的新数据写到新文件造成的阻塞几乎是不可避免的。只要硬盘许可,应该尽量减少AOF rewrite的频率,AOF重写的基础大小默认值64M太小了,可以设到5G以上,默认超过原大小100%大小重写可以改到适当的数值。
  • 如果不Enable AOF,仅靠Master-Slave Repllcation实现高可用性也可以,能省掉一大笔IO,也减少了rewrite时带来的系统波动。代价是如果Master/Slave同时倒掉,会丢失十几分钟的数据,启动脚本也要比较两个Master/Slave中的RDB文件,载入较新的那个,微博就是这种架构。