一、RDB和AOF比较
1.RDB优点和缺点:
RDB优点:能存大数据(AOF文件比RDB大很多,大数据推荐RDN),数据恢复速度快
RDB缺点:数据完整性不能保证,可能丢失最后一次修改的数据;fork时比较耗CPU资源,可能会导致Redis在毫秒级别不能响应客户端请求。
2.AOF优缺点
AOF优点:数据完整性好,最多丢失一秒的数据;文件可读性较好,可以手动修改文件。
AOF缺点:数据恢复速度慢;AOF运行速度慢于RDB
3.只做缓存
如果只需要数据在服务器运行的时候存在,只需要缓存效果,那么可以不使用持久化。
二、同时使用RDB和AOF
如果同时开启了两种持久化,那么redis重启的时候会优先载入AOF文件来恢复原始数据,因为AOF的方式的数据完整性更好。
RDB数据和AOF文件的数据不相同的时候,以AOF文件为准确版本,这时只使用AOF文件恢复数据。那么是否可以不适用AOF,只使用RDB呢?作者建议两者同时用,因为RDB更适合用于备份数据库(AOF在不断变化,不好备份数据库)和快速重启,而且AOF可能有潜在bug,所以建议两个同时使用。
三、RDB和AOF对比(详细)
1.RDB的优点
RDB 是一个非常紧凑的文件,它保存了某个时间点的数据集,非常适用于数据集的备份,比如你可以在每个小时报保存一下过去24小时内的数据,同时每天保存过去30天的数据,这样即使出了问题你也可以根据需求恢复到不同版本的数据集。
RDB 是一个紧凑的单一文件,很方便传送到另一个远端数据中心,非常适用于灾难恢复。
RDB 在保存 RDB 文件时父进程唯一需要做的就是 fork 出一个子进程,接下来的工作全部由子进程来做,父进程不需要再做其他 IO 操作,所以 RDB 持久化方式可以最大化 Redis 的性能。
与AOF相比,在恢复大的数据集的时候,RDB 方式会更快一些。
当 Redis 需要保存 dump.rdb 文件时, 服务器执行以下操作:
Redis 调用forks. 同时拥有父进程和子进程。
子进程将数据集写入到一个临时 RDB 文件中。
当子进程完成对新 RDB 文件的写入时,Redis 用新 RDB 文件替换原来的 RDB 文件,并删除旧的 RDB 文件。
总结来说:RDB 方式可以保存过去一段时间内的数据,并且保存结果是一个单一的文件,可以将文件备份到其他服务器,并且在回复大量数据的时候,RDB 方式的速度会比 AOF 方式的回复速度要快。
2.RDB的缺点
(1)如果你希望在 Redis 意外停止工作(例如电源中断)的情况下丢失的数据最少的话,那么 RDB 不适合你.虽然你可以配置不同的save时间点(例如每隔 5 分钟并且对数据集有 100 个写的操作),是 Redis 要完整的保存整个数据集是一个比较繁重的工作,你通常会每隔5分钟或者更久做一次完整的保存,万一在 Redis 意外宕机,你可能会丢失几分钟的数据。
(2)RDB 需要经常 fork 子进程来保存数据集到硬盘上,当数据集比较大的时候, fork 的过程是非常耗时的,可能会导致 Redis 在一些毫秒级内不能响应客户端的请求。如果数据集巨大并且 CPU 性能不是很好的情况下,这种情况会持续1秒, AOF 也需要 fork ,但是你可以调节重写日志文件的频率来提高数据集的耐久度。
3.AOF的优点
你可以使用不同的 fsync 策略:无 fsync、每秒 fsync 、每次写的时候 fsync .使用默认的每秒 fsync 策略, Redis 的性能依然很好( fsync 是由后台线程进行处理的,主线程会尽力处理客户端请求),一旦出现故障,你最多丢失1秒的数据。
AOF文件是一个只进行追加的日志文件,所以不需要写入seek,即使由于某些原因(磁盘空间已满,写的过程中宕机等等)未执行完整的写入命令,你也也可使用redis-check-aof工具修复这些问题。
Redis 可以在 AOF 文件体积变得过大时,自动地在后台对 AOF 进行重写: 重写后的新 AOF 文件包含了恢复当前数据集所需的最小命令集合。 整个重写操作是绝对安全的,因为 Redis 在创建新 AOF 文件的过程中,会继续将命令追加到现有的 AOF 文件里面,即使重写过程中发生停机,现有的 AOF 文件也不会丢失。 而一旦新 AOF 文件创建完毕,Redis 就会从旧 AOF 文件切换到新 AOF 文件,并开始对新 AOF 文件进行追加操作。
AOF 文件有序地保存了对数据库执行的所有写入操作, 这些写入操作以 Redis 协议的格式保存, 因此 AOF 文件的内容非常容易被人读懂, 对文件进行分析(parse)也很轻松。 导出(export) AOF 文件也非常简单: 举个例子, 如果你不小心执行了 FLUSHALL 命令, 但只要 AOF 文件未被重写, 那么只要停止服务器, 移除 AOF 文件末尾的 FLUSHALL 命令, 并重启 Redis , 就可以将数据集恢复到 FLUSHALL 执行之前的状态。
总结来说:AOF 方式默认每秒钟备份1次,频率很高,它的操作方式是以追加的方式记录日志而不是数据,并且它的重写过程是按顺序进行追加,所以它的文件内容非常容易读懂。可以在某些需要的时候打开 AOF 文件对其编辑,增加或删除某些记录,最后再执行恢复操作。
4.AOF的缺点
对于相同的数据集来说,AOF 文件的体积通常要大于 RDB 文件的体积。
根据所使用的 fsync 策略,AOF 的速度可能会慢于 RDB 。 在一般情况下, 每秒 fsync 的性能依然非常高, 而关闭 fsync 可以让 AOF 的速度和 RDB 一样快, 即使在高负荷之下也是如此。 不过在处理巨大的写入载入时,RDB 可以提供更有保证的最大延迟时间(latency)。
补充:写时复制:
Linux的写时复制:
为了节约物理内存,在调用fork()生成新进程时,新进程与原进程会共享同一内存区.只有当其中一进程(父进程或者子进程都可能会写,这是Linux的设定,当然在Redis中备份的子进程是不会写的)进行写操作时,系统才会为其另外分配内存页面.这就是写时复制机制(copy on write)的意思.
当进程A使用系统调用fork创建一个子进程B时,由于子进程B实际上是父进程A的一个拷贝,因此会拥有与父进程相同的物理页面.为了节约内存和加快创建速度的目标,fork()函数会让子进程B以只读方式共享父进程A的物理页面.同时将父进程A对这些物理页面的访问权限也设成只读.这样,当父进程A或子进程B任何一方对这些已共享的物理页面执行写操作时,都会产生页面出错异常(page_fault int14)中断,此时CPU会执行系统提供的异常处理函数do_wp_page()来解决这个异常。
Redis的写时复制:
在Redis中,RDB和AOF都使用了写时复制(COW,copy on write),但是主要讲RDB的写时复制:如果在复制的时候有新的写入命令,那么对于所有新执行的写入命令,父进程将它们累积到一个内存缓存中,当子进程完成重写工作时,它给父进程发送一个信号,父进程在接收到信号之后,将内存缓存中的所有数据追加到新 的缓存文件中。
因为RDB文件只用作后备用途,建议只在Slave上持久化RDB文件,而且只要15分钟备份一次就够了,只保留save 900 1这条规则。
如果Enalbe AOF,好处是在最恶劣情况下也只会丢失不超过两秒数据,启动脚本较简单只load自己的AOF文件就可以了。代价一是带来了持续的IO,二是AOF rewrite的最后将rewrite过程中产生的新数据写到新文件造成的阻塞几乎是不可避免的。只要硬盘许可,应该尽量减少AOF rewrite的频率,AOF重写的基础大小默认值64M太小了,可以设到5G以上。默认超过原大小100%大小时重写可以改到适当的数值。