什么是Redis的持久化?
RDB(Redis DataBase) 持久化可以在指定的时间间隔内生成数据集的时间点快照(point-in-time snapshot)。
AOF(Append Only File) 持久化记录服务器执行的所有写操作命令,并在服务器启动时,通过重新执行这些命令来还原数据集。 AOF 文件中的命令全部以 Redis 协议的格式来保存,新命令会被追加到文件的末尾。 Redis 还可以在后台对 AOF 文件进行重写(rewrite),使得 AOF 文件的体积不会超出保存数据集状态所需的实际大小。
Redis 还可以同时使用 AOF 持久化和 RDB 持久化。 在这种情况下, 当 Redis 重启时, 它会优先使用 AOF 文件来还原数据集, 因为 AOF 文件保存的数据集通常比 RDB 文件所保存的数据集更完整。
甚至可以关闭持久化功能,让数据只在服务器运行时存在。
了解 RDB 持久化和 AOF 持久化之间的异同是非常重要的, 以下几个小节将详细地介绍这这两种持久化功能, 并对它们的相同和不同之处进行说明。
RDB
RDB的优点
- RDB 非常适用于灾难恢复(disaster recovery)
- 2.RDB 可以最大化 Redis 的性能
- RDB 在恢复大数据集时的速度比 AOF 的恢复速度要快。
RDB的缺点
- 对数据完整性和一致性要求不高
- 在一定间隔时间做一次备份,所以如果redis意外down掉的话,就会丢失最后一次快照后的所有修改
- fork的时候,内存中的数据被克隆了一份,大致2倍的膨胀性需要考虑
在数据集比较庞大时, fork()可能会非常耗时,造成服务器在某某毫秒内停止处理客户端
RDB快照
默认情况下, Redis 将数据库快照保存在名字为 dump.rdb 的二进制文件中。
但是可以对 Redis 进行设置, 让它在“ N 秒内数据集至少有 M 个改动”这一条件被满足时, 自动保存一次数据集。比如说, 以下设置会让 Redis 在满足“ 60 秒内有至少有 1000 个键被改动”这一条件时, 自动保存一次数据集:
save60 100
也可以通过调用 SAVE 或者 BGSAVE , 手动让 Redis 立即进行数据集保存操作。而不去理会设置的自动备份,但save的时候只管保存,其他全部阻塞,bgsave 是在后台异步进行快照,同时还可以进行用户的请求,lastsave 获取最后一次快照的时间
快照的运行方式
当 Redis 需要保存 dump.rdb 文件时, 服务器执行以下操作:
- Redis 调用 fork() ,同时拥有父进程和子进程。
- 子进程将数据集写入到一个临时 RDB 文件中。
- 当子进程完成对新 RDB 文件的写入时,Redis 用新 RDB 文件替换原来的 RDB 文件,并删除旧的 RDB 文件。
AOF
AOF的优点
- AOF 文件是一个只进行追加操作的日志文件(append only log),即使某些原因包含了未写入完整的命令,redis-check-aof 工具也可以轻易地修复这种问题。
- 使用 AOF 持久化会让 Redis 变得非常耐久(much more durable),可以设置不同的 fsync 策略,AOF 的默认策略为每秒钟 fsync 一次,就算发生故障也只会丢失一秒的数据。
- Redis 可以在 AOF 文件体积变得过大时,自动地在后台对 AOF 进行重写。
- AOF 文件有序地保存了对数据库执行的所有写入操作, 这些写入操作以 Redis 协议的格式保存, 因此 AOF 文件的内容非常容易被人读懂, 对文件进行分析(parse)也很轻松。
AOF的缺点
- 相同数据集的数据而言aof文件要远大于rdb文件,恢复速度慢于rdbaof运行效率要慢于rdb,每秒同步策略效率较好,不同步效率和rdb相同。
- AOF 在过去曾经发生过这样的 bug : 因为个别命令的原因,导致 AOF 文件在重新载入时,无法将数据集恢复成保存时的原样。
appeng-only file
如果 Redis 因为某些原因而造成故障停机, 那么服务器将丢失最近写入、且仍未保存到快照中的那些数据。为解决这个问题,你可以通过修改配置文件来打开 AOF 功能:
appendonly yes
打开AOF功能时,每当 Redis 执行一个写的命令时, 这个命令就会被追加到 AOF 文件的末尾。当 Redis 重新启时, 程序就可以通过重新执行 AOF 文件中的命令来达到重建数据集的目的。
AOF重写
因为 AOF 的运作方式是不断地将命令追加到文件的末尾, 所以随着写入命令的不断增加, AOF 文件的体积也会变得越来越大。但是Redis 支持一种有趣的特性: 可以在不打断服务客户端的情况下, 对 AOF 文件进行重建(rebuild)。这很完美的解决了AOF文件体积的问题。执行 下面命令
BGREWRITEAOF
Redis 将生成一个新的 AOF 文件, 这个文件包含重建当前数据集所需的最少命令。
AOF的同步策略
通过配置 Redis 多久才将数据 fsync 到磁盘一次。有三个选项:
always:每次有新命令追加到 AOF 文件时就执行一次 fsync 。非常慢,也非常安全。
everysec:每秒 fsync 一次。足够快(和使用 RDB 持久化差不多),并且在故障时只会丢失 1 秒钟的数据。
no:从不 fsync 。将数据交给操作系统来处理。更快,也更不安全的选择。
推荐(并且也是默认)的措施为每秒 fsync 一次, 这种 fsync 策略可以兼顾速度和安全性。
因意外导致AOF文件出错,怎么进行修复?
Redis 在重启时会拒绝载入这个 AOF 文件, 从而确保数据的一致性不会被破坏。当发生这种情况时, 可以用以下方法来修复出错的 AOF 文件:
- 为现有的 AOF 文件创建一个备份。
- 使用 Redis 附带的 redis-check-aof 程序,对原来的 AOF 文件进行修复。
redis-check-aof --fix
3. (可选)使用 diff -u 对比修复后的 AOF 文件和原始 AOF 文件的备份,查看两个文件之间的不同之处。
4. 重启 Redis 服务器,等待服务器载入修复后的 AOF 文件,并进行数据恢复。
AOF的运作方式
AOF 重写和 RDB 创建快照一样,都巧妙地利用了写时复制机制。
以下是 AOF 重写的执行步骤:
1. Redis 执行 fork() ,现在同时拥有父进程和子进程。
2. 子进程开始将新 AOF 文件的内容写入到临时文件。
3. 对于所有新执行的写入命令,父进程一边将它们累积到一个内存缓存中,一边将这些改动追加到现有 AOF 文件的末尾: 这样即使在重写的中途发生停机,现有的 AOF 文件也还是安全的。
4. 当子进程完成重写工作时,它给父进程发送一个信号,父进程在接收到信号之后,将内存缓存中的所有数据追加到新 AOF 文件的末尾。
5. 搞定!现在 Redis 原子地用新文件替换旧文件,之后所有命令都会直接追加到新 AOF 文件的末尾。
怎么从RDB持久化切换到AOF持久化
在 Redis 2.2 或以上版本,可以在不重启的情况下,从 RDB 切换到 AOF :
1. 为最新的 dump.rdb 文件创建一个备份。
2. 将备份放到一个安全的地方。
3. 执行以下两条命令:
redis-cli> config set appendonly yes
redis-cli> config set save ""
4. 确保命令执行之后,数据库的键的数量没有改变。
5. 确保写命令会被正确地追加到 AOF 文件的末尾。
注:
第一条命令开启了 AOF 功能: Redis 会阻塞直到初始 AOF 文件创建完成为止, 之后 Redis 会继续处理命令请求, 并开始将写入命令追加到 AOF 文件末尾。
第二条命令用于关闭 RDB 功能。 这一步是可选的, 如果你愿意的话, 也可以同时使用 RDB 和 AOF 这两种持久化功能。
别忘了在 redis.conf 中打开 AOF 功能! 否则, 服务器重启之后, 之前通过 CONFIGSET 设置的配置就会被遗忘, 程序仍然按原来的配置来启动服务器。
备份Redis数据库
请将下面这句话铭记于心: 一定要备份你的数据库!一定要备份你的数据库!一定要备份你的数据库!重要的是说三遍
磁盘故障, 节点失效, 诸如此类的问题都可能让你的数据消失不见, 不进行备份你会哭的。
Redis 对于数据备份做的非常友好, 因为你可以在服务器运行的时候对 RDB 文件进行复制。当服务器要创建一个新的 RDB 文件时, 它先将文件的内容保存在一个临时文件里面, 当临时文件写入完毕时, 程序才使用rename(2) 原子地用临时文件替换原来的 RDB 文件。
以下是官网给的一些建议:
创建一个定期任务(cron job), 每小时将一个 RDB 文件备份到一个文件夹, 并且每天将一个 RDB 文件备份到另一个文件夹。
确保快照的备份都带有相应的日期和时间信息, 每次执行定期任务脚本时, 使用 find 命令来删除过期的快照: 比如说, 你可以保留最近 48 小时内的每小时快照, 还可以保留最近一两个月的每日快照。
至少每天一次, 将 RDB 备份到你的数据中心之外, 或者至少是备份到你运行 Redis 服务器的物理机器之外。
性能建议
因为RDB文件只用作后备用途,建议只在Slave上持久化RDB文件,而且只要15分钟备份一次就够了,只保留save 900 1这条规则。
如果Enalbe AOF,好处是在最恶劣情况下也只会丢失不超过两秒数据,启动脚本较简单只load自己的AOF文件就可以了。代价一是带来了持续的IO,二是AOF rewrite的最后将rewrite过程中产生的新数据写到新文件造成的阻塞几乎是不可避免的。只要硬盘许可,应该尽量减少AOF rewrite的频率,AOF重写的基础大小默认值64M太小了,可以设到5G以上。默认超过原大小100%大小时重写可以改到适当的数值。
如果不Enable AOF ,仅靠Master-Slave Replication 实现高可用性也可以。能省掉一大笔IO也减少了rewrite时带来的系统波动。代价是如果Master/Slave同时倒掉,会丢失十几分钟的数据,启动脚本也要比较两个Master/Slave中的RDB文件,载入较新的那个。新浪微博就选用了这种架构。