【Redis3.0.x】持久化
Redis3.0.x 持久化
概述
Redis 提供了两种不同的持久化方式:
- RDB(Redis DataBase)持久化,可以在指定的时间间隔内生成数据集的时间点快照。
- AOF(Append Only File)持久化,记录服务器执行的所有写操作命令,并在服务器启动时,通过重新执行这些命令来还原数据集。AOF 文件中的命令全部以 Redis 协议的格式来保存,新命令会被追加到文件的末尾。Redis 还可以在后台对 AOF 文件进行重写,使得 AOF 文件的体积不会超出保存数据集状态所需的实际大小。
- 可以同时使用 RDB 和 AOF 持久化,当 Redis 重启时,它会优先使用 AOF 文件来还原数据集,因为 AOF 文件 通常比 RDB 文件保存的数据集更完整。
fork:它的作用是复制一个与当前进程一样的进程。新进程的所有数据(变量、环境变量、程序计数器等)数值都和原进程一致,但是是一个全新的进程,并作为原进程的子进程。
RDB
RDB 优点
RDB 优点:
- RDB 是一种表示某个即时点的 Redis 数据的紧凑文件,RDB文件适合用于备份。
- RDB 非常适合于灾难恢复,作为一个紧凑的单一文件,可以被传输到远程的数据中心。
- RDB 最大化了 Redis 的性能,因为 Redis 父进程持久化时唯一需要做的是启动(fork)一个子进程,由子进程完成所有剩余工作。父进程实例不需要执行像 磁盘 IO 这样的操作。
- RDB 在重启时还原数据集比 AOF 要快。
RDB 缺点
RDB 缺点:
- RDB 可能不能很好的完成最小化数据丢失。
- RDB 需要经常调用 fork 子进程来持久化到磁盘,如果数据集很大的话,fork 会比较耗时。
RDB 快照
默认情况下,Redis 保存数据集快照到磁盘,默认名为 dump.rdb 的二进制文件。可以设置让 Redis 在 N 秒内至少有 M 次数据集改动时 保存数据集,或者也可以手动调用 SAVE 或者 BGSAVE 命令进行快照保存。使用 config set save ""
关闭 RDB 持久化。
其中,使用 SAVE 时只管保存,其它不管,全部阻塞。使用 BGSAVE 会在后台异步进行快照操作,快照同时还可以响应客户端请求。可以通过 lastsave 命令获取最后一次成功执行快照的时间。
RDB 使用
正常还原数据集:
- 开启 RDB 持久化
- 将 RDB 备份文件复制到安装目录,使用
config get dir
获得安装目录 - 重启 Redis 然后重新加载
异常还原数据集:
- 开启 RDB 持久化
- 将 RDB 备份文件复制到安装目录
- 使用
redis-check-rdb --fix
对文件进行修复 - 重启 Redis 然后重新加载
快照的运行方式
当 Redis 需要保存 dump.rdb 文件时,服务器执行以下操作:
- Redis 调用 fork,同时拥有父进程和子进程。
- 子进程将数据集写入到一个临时 RDB 文件中。
- 当子进程完成对新 RDB 文件的写入时,Redis 用新 RDB 文件替换原来的 RDB 文件,并删除旧的 RDB 文件。
AOF
AOF 优点
AOF 优点:
- AOF 能很好的完成最小化数据丢失。
- AOF 是一个追加文件,所以不需要定位,在断电时也没有损坏问题。即使由于某种原因文件末尾是一个写到一半的命令,使用
redis-check-aof
工具也可以很轻易的修复。 - AOF 变得很大时,Redis 会自动在后台进行重写。
- AOF 里面包含一个个的操作,以易于理解和解析的格式存储,可以轻易的导出一个 AOF。
AOF 缺点
AOF 缺点:
- 对同样的数据集,AOF 通常要大于 RDB。
- AOF 可能比 RDB 慢,不过这取决于准确的 fsync 策略。有三种 fsync 策略:每次有新命令追加到 AOF 时就执行一次 fsync,非常慢但非常安全;每秒 fsync 一次,足够快,并且在故障时只会丢失 1 秒钟的数据;从不 fsync,将数据交给操作系统来处理。最快但不安全。
AOF 使用
使用 config set appendonly yes/no
开启或关闭 AOF 持久化。
正常还原数据集:
- 开启 AOF 持久化
- 将 AOF 备份文件复制到安装目录
- 重启 Redis 然后重新加载
异常还原数据集:
- 开启 AOF 持久化
- 将 AOF 备份文件复制到安装目录
- 使用
redis-check-aof --fix
对文件进行修复 - 重启 Redis 然后重新加载
AOF 重写
AOF 重写是绝对安全的,因为 Redis 继续往旧的文件中追加,使用创建当前数据集所需的最小操作集合来创建一个全新的文件,一旦第二个文件创建完毕,Redis 就会切换这两个文件,并开始往新文件追加。
重写的运行方式
和快照的运行方式类似,当需要 AOF 重写时,服务器执行以下操作:
- Redis 调用 fork,同时拥有父进程和子进程。
- 子进程开始向一个临时文件中写 AOF。
- 父进程在一个内存缓冲区中积累新的变更,同时将新的变更写入旧的 AOF。
- 当子进程完成重写文件,父进程收到一个信号,追加内存缓冲区到子进程创建的文件末尾。
- 最后 Redis 原子性地重命名旧文件为新的,然后开始追加新数据到新文件。
触发重写的机制:
- Redis 会记录上次重写时的 AOF 大小,默认配置是当 AOF 大小是上次 rewrite 后大小的一倍,并且文件大于 64M 时触发。
RDB 转换到 AOF
大致步骤为:
- 创建最近的 RDB 文件的备份,并将备份保存到安全位置。
- 执行
config set appendonly yes
,开启 AOF, - 执行
config set save ""
,关闭 RDB,这一步是可选的。
RDB 和 AOF 的相互作用
Redis2.4 以上的版本会确保在 RDB 快照创建时不触发 AOF 重写,或者在 AOF 重写时不允许 BGSAVE 操作,以避免 Redis 后台进程同时做繁重的磁盘I /O 操作。
当创建 RDB 快照时对于用户使用 BGREWRITEAOF 明确发起的日志重写操作,server 会立刻回应一个 状态码 告知用户操作将会被执行,并且是在快照创建完成后,重写操作开始被执行。
性能建议
因为 RDB 文件只用作后背用途,建议只在 Slave 上持久化 RDB 文件,而且只要 15 分钟备份一次就可以了,即 save 900 1
。
如果开启 AOF,好处是在最坏的情况下也只会丢失不超过两秒的数据,而且启动脚本较简单,载入自己的那个 AOF 文件。代价是带来了持续的 IO,而且 AOF rewrite 过程中将产生的新数据写到新文件造成的阻塞几乎是不可避免的。并且只要硬盘许可,应该尽量减少 AOF rewrite 的频率,AOF 重写的基础大小默认值为 64M,显然太小了,可以设置到 5G 以上,而且还要修改重写率。
如果不开启 AOF,仅靠 Master-Slave Replication 实现高可用性也可以。好处是省掉了 IO,同时减少了 rewrite 过程对系统带来的影响。代价是如果 Master-Slave 同时挂掉,会丢失十几分钟的数据,而且启动脚本较复杂,需要比较 Master-Slave 的两个 RDB 文件,载入较新的那个 RDB 文件。