二者的区别
RDB 持久化是指在指定的时间间隔内将内存中的数据集快照写入磁盘,实际操作过程是 fork 一个子进程,先将数据集写入临时文件,写入成功后,再替换之前的文件,用二进制压缩存储
AOF 持久化以日志的形式记录服务器所处理的每一个增删改操作,以文本的方式记录,可以打开文件看到详细的操作记录
二者优缺点
RDB 优势
RDB 会生成多个数据文件,每个数据文件都代表了某一个时刻中 Redis 的数据,这种多个数据文件的方式。比如,可能打算每个小时归档一次最近 24 小时的数据,同时还要每天归档一次最近 30 天的数据。通过这样的备份策略,一旦系统出现灾难性故障,可以非常容易的进行恢复。同时,可以将这种完整的数据文件压缩后发送到一些远程的安全存储上去。适合做冷备
直接基于 RDB 数据文件来重启和恢复 Redis 进程,恢复效率会更高
RDB 对 Redis 对外提供的读写服务,影响非常小,可以让 Redis 保持高性能,因为 Redis 主进程只需要 fork 一个子进程,让子进程执行磁盘 IO 操作来进行 RDB 持久化
RDB 劣势
如果想保证数据的高可用性,即最大限度的避免数据丢失,那么 RDB 将不是一个很好的选择。因为系统一旦在定时持久化之前出现宕机现象,此前没有来得及写入磁盘的数据都将丢失
由于 RDB 是通过 fork 子进程来协助完成数据持久化工作的,因此,如果当数据集较大时,可能会导致整个服务器停止服务几百毫秒,甚至是 1 秒钟
一般不要让 RDB 的间隔太长,否则每次生成的 RDB 文件太大了,对 Redis 本身的性能也会有影响
AOF 优势
该机制可以带来更高的数据安全性。Redis 提供了 3 种同步策略:每秒同步、每修改同步和不同步。事实上,每秒同步也是异步完成的,其效率也是非常高的,所差的是一旦系统出现宕机现象,那么这一秒钟之内修改的数据将会丢失。而每修改同步,我们可以将其视为同步持久化,即每次发生的数据变化都会被立即记录到磁盘中。可以预见,这种方式在效率上是最低的。至于无同步,无需多言
由于该机制对日志文件的写入操作采用的是 append 模式,因此在写入过程中即使出现宕机现象,也不会破坏日志文件中已经存在的内容。然而如果本次操作只是写入了一半数据就出现了系统崩溃问题,在 Redis 下一次启动之前,可以通过 redis-check-aof 工具来帮助解决数据一致性的问题
如果日志过大,Redis 可以自动启用 rewrite 机制(后台重写,不影响客户端的读写)。即 Redis 以 append 模式不断的将修改数据写入到老的磁盘文件中,同时 Redis 还会创建一个新的文件用于记录此期间有哪些修改命令被执行。因此在进行 rewrite 切换时可以更好的保证数据安全性
AOF 日志文件的命令通过非常可读的方式进行记录,这个特性非常适合做灾难性的误删除的紧急恢复。比如某人不小心用 flushall 命令清空了所有数据,只要这个时候后台 rewrite 还没有发生,那么就可以立即拷贝 AOF 文件,将最后一条 flushall 命令给删了,然后再将该 AOF 文件放回去,就可以通过恢复机制,自动恢复所有数据
AOF 劣势
对于同一份数据来说,AOF 日志文件通常比 RDB 数据快照文件更大,靠重写来弥补
AOF 开启后,支持的写 QPS 会比 RDB 支持的写 QPS 低,因为要将命令写到 AOF 缓冲区。此外,还要定时 fsync 一次日志文件
通过回放 AOF 日志中的写入指令来重新构建整个数据集,数据恢复速度比较慢
定期的备份需要自己手写脚本去做,做冷备不太合适
以前 AOF 发生过 bug,就是通过 AOF 记录的日志,进行数据恢复的时候,没有恢复一模一样的数据出来。所以,类似 AOF 这种较为复杂的基于命令日志回放的方式,比基于 RDB 每次持久化一份完整的数据快照文件的方式,更加脆弱一些,容易有 bug。不过 AOF 就是为了避免 rewrite 过程导致的 bug,因此每次 rewrite 并不是基于旧的指令日志进行 merge 的,而是基于当时内存中的数据进行指令的重新构建,这样健壮性会好很多
二者选择的标准
- 不要仅仅使用 RDB,因为那样会导致丢失数据
- 也不要仅仅使用 AOF,因为那样有两个问题,第一,通过 AOF 做冷备,没有 RDB 做冷备,恢复速度快;第二,RDB 每次简单粗暴生成数据快照,更加健壮,可以避免 AOF 这种复杂的备份和恢复机制的 bug
- 综合使用 AOF 和 RDB 两种持久化机制,用 AOF 来保证数据不丢失,作为数据恢复的第一选择;用 RDB 来做不同程度的冷备,在 AOF 文件都丢失或损坏不可用的时候,还可以使用 RDB 来进行快速的数据恢复