Redis持久化方式

AOF 持久化

AOF 机制对每条写入命令作为日志,以 append-only 的模式写入一个日志文件中,
在 redis 重启的时候,可以通过回放 AOF 日志中的写入指令来重新构建整个数据集。
Redis默认情况是不开启AOF的。重启时再重新执行AOF文件中的命令来恢复数据。它主要解决数据持久化的实时性问题。

AOF是执行完命令后才记录日志的。为什么不先记录日志再执行命令呢?这是因为Redis在向AOF记录日志时,
不会先对这些命令进行语法检查,如果先记录日志再执行命令,
日志中可能记录了错误的命令,Redis使用日志回复数据时,可能会出错。
正是因为执行完命令后才记录日志,所以不会阻塞当前的写操作。

但是会存在两个风险:

  1. 更执行完命令还没记录日志时,宕机了会导致数据丢失
  2. AOF不会阻塞当前命令,但是可能会阻塞下一个操作。

AOF机制的三种写回策略 appendfsync:

  • always 同步写回,每个子命令执行完,都立即将日志写回磁盘。
  • everysec 每个命令执行完,只是先把日志写到AOF内存缓冲区,每隔一秒同步到磁盘。
  • no 只是先把日志写到AOF内存缓冲区,有操作系统去决定何时写入磁盘。

always同步写回,可以基本保证数据不丢失,no策略则性能高但是数据可能会丢失,一般可以考虑折中选择everysec

AOF优点:

  • 数据保证:我们可以设置fsync策略,一般默认是everysec,
    也可以设置每次写入追加,所以即使服务死掉了,也最多丢失一秒数据
  • 自动缩小:当aof文件大小到达一定程度的时候,后台会自动的去执行aof重写,
    此过程不会影响主进程,重写完成后,新的写入将会写到新的aof中,
    旧的就会被删除掉。但是此条如果拿出来对比rdb的话还是没有必要算成优点,只是官网显示成优点而已。

AOF缺点:

  • 性能相对较差:它的操作模式决定了它会对redis的性能有所损耗。
  • 体积相对更大:尽管是将aof文件重写了,但是毕竟是操作过程和操作结果仍然有很大的差别,体积也毋庸置疑的更大。
  • 恢复速度更慢:AOF 在过去曾经发生过这样的 bug:因为个别命令的原因,导致 AOF 文件在重新载入时,
    无法将数据集恢复成保存时的原样。测试套件里为这种情况添加了测试: 它们会自动生成随机的、复杂的数据集,
    并通过重新载入这些数据来确保一切正常。虽然这种 bug 在 AOF 文件中并不常见,但是对比来说,RDB几乎是不可能出现这种bug的。

RDB持久化

RDB,就是把内存数据以快照的形式保存到磁盘上。和AOF相比,它记录的是某一时刻的数据,并不是操作。
RDB持久化,是指在指定的时间间隔内,执行指定次数的写操作,将内存中的数据集快照写入磁盘中,它是Redis默认的持久化方式。
执行完操作后,在指定目录下会生成一个dump.rdb文件,Redis 重启的时候,通过加载dump.rdb文件来恢复数据。

RDB的优点:

  • 体积更小:相同的数据量rdb数据比aof的小,因为rdb是紧凑型文件。
  • 恢复更快:因为rdb是数据的快照,基本上就是数据的复制,不用重新读取再写入内存。
  • 性能更高:父进程在保存rdb时候只需要fork一个子进程,无需父进程的进行其他io操作,也保证了服务器的性能。

RDB的缺点:

  • 故障丢失:因为rdb是全量的,我们一般是使用shell脚本实现30分钟或者1小时或者每天对redis进行rdb备份,(注,也可以是用自带的策略),但是最少也要5分钟进行一次的备份,所以当服务死掉后,最少也要丢失5分钟的数据。
  • 耐久性差:相对aof的异步策略来说,因为rdb的复制是全量的,即使是fork的子进程来进行备份,当数据量很大的时候对磁盘的消耗也是不可忽视的,尤其在访问量很高的时候,fork的时间也会延长,导致cpu吃紧,耐久性相对较差。

拓展阅读

如何选择RDB和AOF
如果数据不能丢失,RDB和AOF混用
如果只作为缓存使用,可以承受几分钟的数据丢失的话,可以只使用RDB。
如果只使用AOF,优先使用everysec的写回策略。

参考

https://worktile.com/kb/ask/22901.html
https://zhuanlan.zhihu.com/p/463781090