画江湖之 Redis持久化

redis持久化

Redis 提供两种持久化解决方案:RDB 持久化和 AOF 持久化

RDB 持久化:

可以在指定时间间隔内,生成数据集在这个时间点的快照;
采用 RDB 持久化方案时,Redis 会每隔一段时间对数据集进行快照备份,换句话说这种方案在服务器发生故障时可能造成数据的丢失。所以,如果对数据的完整性有比较强烈的要求,可能不太适用这种备份方案,即它适用于做数据的备份;
RDB 持久化策略

  • 自动执行 RDB 持久化
    可以通过配置 redis.windows.conf 配置文件来完成

Redis 高级
这里的 save 指令表示「在 x 秒内有 n 个及以上键被改动」则会自动保存一次数据集,比如配置中的 save 60 10000 表示如果在 60 秒内有 10000 个及以上的键被改动时则执行保存数据集操作。
我们在启动 Redis 服务时,服务器会读取配置文件中的配置,所以 RDB 持久化策略会自动启 动,当满足条件时会执行持久化处理

  • 手动执行 RDB 持久化
    ,我们可以使用 SAVE 或 BGSAVE 命令 来手动执行 RDB 持久化处理。
    虽然,savebgsave 都可以手动的执行 RDB 持久化处理。但是它们的工作模式完全不同。
    • 执行 SAVE 命令时,会阻塞 Redis 主进程,直到保存完成为止。在主进程阻塞期间,服务器不能处理客户端的任何请求
    • BGSAVE 则 fork 出一个子进程,子进程负责执行保存处理,并在保存完成之后向主进程发送信号,通知主进程保存完成。所以 Redis 服务器在 BGSAVE 执行期间仍然可以继续处理客户端的请求
      注意:虽然通过 SAVE 命令可以执行 RDB 持久化处理,但是它的运行原理同自动持久化中的 save 指令是完全不同的,save 指令的工作原理同 BGSAVE 指令。

优点

  • RDB 是一个非常紧凑(compact)的文件(笔者注:因为 RDB 持久化文件 dump.rdb 将数据集以二级制形式保存),它保存了 Redis 在某个时间点上的数据集。 这种文件非常适合用于进行备份。
  • RDB 非常适用于灾难恢复(disaster recovery):它只有一个文件,并且内容都非常紧凑,可以(在加密后)将它传送到别的数据中心。
  • RDB 可以最大化 Redis 的性能:父进程在保存 RDB 文件时唯一要做的就是 fork 出一个子进程,然后这个子进程就会处理接下来的所有保存工作,父进程无须执行任何磁盘 I/O 操作。
  • RDB 在恢复大数据集时的速度比 AOF 的恢复速度要快。

缺点

  • 可能在服务器故障时导致数据丢失,因为 RDB 采用的是定时保存数据的机制,所以可能导致下次保存数据时的数据丢失。
  • 可能导致服务器无法处理客户端处理,这是由于 RDB 执行非阻塞(BGSAVE 或 save 指令)保存时,会 fock 出子进程,如果待保存的数据集非常大可能会非常耗时。

AOF 持久化:

AOF(append only file):只进行追加操作的文件。默认情况下,Redis 会禁用 AOF 重写,如需开启我们需要到配置文件中将 appendonly 指令配置为 yes(默认:no 不启用)

启用 AOF 持久化方案后,当我们执行类似 SET 设置(或修改)命令时,Redis 会将命令以 Redis 通信协议 文本保存到 appendonly.aof 文件中。

aof持久化策略

AOF 持久化方案提供 3 种不同时间策略将数据同步到磁盘中,同步策略通过 appendfsync 指令完成:

  • everysec(默认):表示每秒执行一次 fsync 同步策略,效率上同 RDB 持久化差不多。由于每秒同步一次,所以服务器故障时会丢失 1 秒内的数据。
  • always: 每个写命令都会调用 fsync 进行数据同步,最安全但影响性能。
  • no: 表示 Redis 从不执行 fsync,数据将完全由内核控制写入磁盘。对于 Linux 系统来说,每 30 秒写入一次。

    使用是推荐采用默认的 everysec 每秒同步策略,兼顾安全与效率。

AOF 持久化的运行原理
  1. Redis 主进程执行 fork () 创建出子进程。
  2. 子进程开始将新 AOF 文件的内容写入到临时文件。
  3. 对于所有新执行的写入命令,父进程一边将它们累积到一个内存缓存中,一边将这些改动追加到现有 AOF 文件的末尾: 这样即使在重写的中途发生停机,现有的 AOF 文件也还是安全的。
  4. 当子进程完成重写工作时,它给父进程发送一个信号,父进程在接收到信号之后,将内存缓存中的所有数据追加到新 AOF 文件的末尾。
  5. 搞定!现在 Redis 原子地用新文件替换旧文件,之后所有命令都会直接追加到新 AOF 文件的末尾。
优化 AOF 备份文件

我们知道 AOF 的运行原理是不断的将写入的命令以 Redis 通信协议的数据格式追加到 .aof 文件末尾,这就会导致文件的体积不断增大。

如果所有的命令完全不同到没有关系。

但是,如果命令处理类似计数器的功能,比如执行 100 次 INCR(incr counter)处理,AOF 文件会保存全部的 INCR 命令的执行记录,但实际上我们知道这些处理的结果同 set counter 100 并无二致。这就导致我们的 .aof 多存储了 99 条命令记录。

这时,我们就可以使用 Redis 提供的 BGREWRITEAOF 重写命令,将 AOF 文件进行重写优化。

现在我们通过 BGREWRITEAOF 命令对文件进行重写处理:

127.0.0.1:6380> BGREWRITEAOF
Background append only file rewriting started  
优点
  • 提供比 RDB 持久化方案更安全的数据,由于默认采用每秒进行持久化处理,所有即使服务器重启或宕机,最多也就丢失 1 秒内的数据。
  • AOF 文件有序地保存了对数据库执行的所有写入操作, 这些写入操作以 Redis 协议的格式保存, 因此 AOF 文件的内容非常容易被人读懂, 对文件进行分析(parse)也很轻松
缺点
  • 相比于 RDB 持久化,AOF 文件会比 RDB 备份文件大得多。
  • AOF 持久化的速度可能比 RDB 持久化速度慢。
  • AOF 在过去曾经发生过这样的 bug : 因为个别命令的原因,导致 AOF 文件在重新载入时,无法将数据集恢复成保存时的原样。 (举个例子,阻塞命令 BRPOPLPUSH 就曾经引起过这样的 bug 。) 测试套件里为这种情况添加了测试: 它们会自动生成随机的、复杂的数据集, 并通过重新载入这些数据来确保一切正常。 虽然这种 bug 在 AOF 文件中并不常见, 但是对比来说, RDB 几乎是不可能出现这种 bug 的。

Redis 数据恢复

通过前面的学习我们了解到 Redis 是如何执行 RDB 和 AOF 持久化处理的,现在我们简单了解下 Redis 是如何恢复 RDB 或 AOF 备份中的数据。

我们知道 Redis 是一种内存型的 NoSQL 数据库(或者说数据结构),当服务重启或宕机都会导致内存中的数据丢失。

所以,当 Redis 服务器重启或恢复时,它会进行读取 RDB 或 AOF 文件(如果存在的话)处理,将文件中的数据重新载入内存实现数据恢复操作。

Redis 数据恢复采用两套恢复方案:

  • 开启 AOF 持久化方案时,优先采用 AOF 文件进行数据恢复

这个很好理解,因为 AOF 持久化方案的数据保存是秒级的,所以相对于 RDB 持久化数据更完整,所以在启动 Redis 服务器是,会在 AOF 启用时有限载入 AOF 文件进行数据还原。

  • 未开启 AOF 持久化方案是,Redis 通过载入 RDB 文件进行数据恢复

持久化配置选项

RDB 配置位于 SNAPSHOTTING 配置节点。

  • 开启 / 关闭 RDB 持久化功能
  1. 严格来说 Redis 没有提供类似 AOF 的 appendonly 指令来开启 RDB 持久化功能,我们可以通过注释掉 save 指令来关闭 RDB 备份方案。
#save 900 1
#save 300 10
#save 60 10000
  1. 或者使用 config set save “” 命令来关闭重写,但是如果仅使用这条命令,仅在当前服务器运行时生效,所以重启服务器依然从配置文件读取 RDB 重写规则。如果想永久生效,可以运行 config rewrite 命令,将 config set save 命令结果写入到配置文件。执行完 config rewrite 命令后会直接删除 redis.windows.conf 配置中的 save 指令。
  • 是否启用压缩

通过 rdbcompression 指令完成,默认 yes 进行压缩。

  • 修改备份文件名

使用 dbfilename 指令,默认值 dump.rdb

  • 修改备份文件存储目录

使用 dir 指令,默认值 your_redis_path。另外 AOF 备份数据同样会保存到该目录下。

AOF 持久化配置选项

AOF 配置位于 APPEND ONLY MODE 配置节点。

  • 开启 / 关闭 AOF 持久化功能

开启 AOF 持久化功能,通过 appendonly 指令完成,取值范围 yes / no,默认:no 不开启 AOF 重写。

  • 修改备份文件名

appendfilename 指令完成,默认值 appendonly.aof

  • 设置持久化执行策略

请参考前文 appendfsync 指令说明。

  • AOF 备份文件重写规则配置

之前我们通过使用命令 BGREWRITEAOF 对 AOF 执行重写,但是当我们启用 AOF 持久化功能后,Redis 默认会启用 AOF 重写优化,这个工作有两条指令完成:

auto-aof-rewrite-percentage 100
auto-aof-rewrite-min-size 64mb

auto-aof-rewrite-percentage 指令表示,本次执行 AOF 重写时,当 AOF 文件的大小是上次执行重写时文件的百分之多少才可以自动重写。默认: 100 表示本次重写时的 AOF 文件是上次 2 倍可以自动重写。

auto-aof-rewrite-min-size 这个指令用于设置进行 AOF 文件自动重写的最小文件大小。

换言之,这两条配置表示:当 AOF 文件大小达到 64mb 时,才开始自动进行重写。下一次只有当文件大小需达到 128 mb 才能再次重写,以此类推。

  • 自动修复出错的 AOF 数据

当我们的 Redis 服务器宕机时,可能导致 AOF 文件的尾部数据不完整,在重启 Redis 服务器可能导致数据不一致。此时可以通过:

aof-load-truncated 指令在启动 Redis 自动修复文件。它的取值范围是 yes / no,默认为 yes 重启时自动修复。

同样的我们也可以通过 redis-check-aof –fix 修复工具手动进行修复

本节参考资料 blog.phpzendo.com/?p=442

本作品采用《CC 协议》,转载必须注明作者和本文链接
Luson
《L01 基础入门》
我们将带你从零开发一个项目并部署到线上,本课程教授 Web 开发中专业、实用的技能,如 Git 工作流、Laravel Mix 前端工作流等。
《L04 微信小程序从零到发布》
从小程序个人账户申请开始,带你一步步进行开发一个微信小程序,直到提交微信控制台上线发布。
讨论数量: 2

所以为什么是画江湖,也没见着画呀

2年前 评论
Luson (楼主) 2年前

帅哥,这句话是不是矛盾了注意:虽然通过 SAVE 命令可以执行 RDB 持久化处理,但是它的运行原理同自动持久化中的 save 指令是完全不同的,save 指令的工作原理同 BGSAVE 指令。,SAVE的运行原理同自动持久化的save指令完全不同?

2年前 评论
Luson (楼主) 2年前
NoTurningBack (作者) 2年前

讨论应以学习和精进为目的。请勿发布不友善或者负能量的内容,与人为善,比聪明更重要!