redis持久化

fxz大约 20 分钟redis缓存持久化

redis持久化

Redis 提供了3种持久化机制来保证数据在断电或重启后不会丢失:

  • 快照(snapshotting,RDB): RDB 以指定的时间间隔执行数据集的时间点快照。
  • 只追加文件(append-only file, AOF): AOF 持久性记录服务器接收到的每个写操作。然后可以在服务器启动时再次重播这些操作,从而重建原始数据集。命令使用与 Redis 协议本身相同的格式进行记录。
  • RDB 和 AOF 的混合持久化(Redis 4.0 新增)

RDB

怎么运行

Redis 提供了两个命令来生成 RDB 快照文件:

  • save : 同步保存操作,会阻塞 Redis 主线程;
  • bgsave : fork 出一个子进程,子进程执行,不会阻塞 Redis 主线程,默认选项。

每当 Redis 需要将数据集转储到磁盘时,就会发生以下情况:

  • Redis forkopen in new window子进程。我们现在有一个子进程和一个父进程。
  • 子进程开始将数据集写入临时 RDB 文件。
  • 当子进程写完新的 RDB 文件后,它会替换旧的 RDB 文件(Copy-on-Write)。

优点

  • RDB 文件非常适合备份。例如,您可能希望在最近 24 小时内每小时归档一次 RDB 文件,并在 30 天内每天保存一个 RDB 快照。这使您可以在发生灾难时轻松恢复不同版本的数据集。
  • RDB 非常适合灾难恢复,它是一个紧凑的文件,可以传输到远程数据中心或 Amazon S3(可能是加密的)。
  • RDB 最大限度地提高了 Redis 的性能,因为 Redis 父进程为了持久化需要做的唯一工作就是派生一个子进程,该子进程将完成其余所有工作。父进程永远不会执行磁盘 I/O 或类似操作。
  • 与 AOF 相比,RDB 允许更快地重新启动大数据集。

缺点

  • 如果您需要在 Redis 停止工作(例如断电后)时最大程度地减少数据丢失的可能性,那么 RDB 并不好。您可以在生成 RDB 的位置配置不同的保存点(例如,在至少五分钟并对数据集进行 100 次写入后)。但是,您通常会每五分钟或更长时间创建一个 RDB 快照,因此,如果 Redis 由于任何原因在没有正确关闭的情况下停止工作,您应该做好丢失最新分钟数据的准备。
  • RDB 需要经常 fork() 才能使用子进程持久保存在磁盘上。如果数据集很大,fork() 可能会非常耗时,并且如果数据集很大并且 CPU 性能不是很好,可能会导致 Redis 停止为客户端提供服务几毫秒甚至一秒。AOF 还需要 fork() 但频率较低,您可以调整重写日志的频率,而无需牺牲持久性。

AOF

怎么运行

Redis 6.0 之后已经默认是开启了AOF,每次 Redis 收到更改数据集的命令(例如SETopen in new window)时,它都会将其追加到 AOF 中。当您重新启动 Redis 时,它将重放 AOF 以重建状态。

从Redis 7.0.0开始,Redis使用多部分AOF机制。即把原来的单个AOF文件拆分为基础文件(最多一个)和增量文件(可能不止一个)。基础文件表示重写 AOF 时存在的数据的初始(RDB 或 AOF 格式)快照open in new window。增量文件包含自上次创建基本 AOF 文件以来的增量更改。所有这些文件都放在单独的目录中,并由清单文件跟踪。

命令追加(append):所有的写命令会追加到 AOF 缓冲区中。

文件写入(write):将 AOF 缓冲区的数据写入到 AOF 文件中。这一步需要调用write函数(系统调用),write将数据写入到了系统内核缓冲区之后直接返回了(延迟写)。注意!!!此时并没有同步到磁盘。

文件同步(fsync):AOF 缓冲区根据对应的持久化方式( fsync 策略)向硬盘做同步操作。这一步需要调用 fsync 函数(系统调用), fsync 针对单个文件操作,对其进行强制硬盘同步,fsync 将阻塞直到写入磁盘完成后返回,保证了数据持久化。

文件重写(rewrite):随着 AOF 文件越来越大,需要定期对 AOF 文件进行重写,达到压缩的目的。

重启加载(load):当 Redis 重启时,可以加载 AOF 文件进行数据恢复。

日志重写

随着写操作的执行,AOF 会变得越来越大。例如,如果您将计数器递增 100 次,则最终数据集中会出现一个包含最终值的键,但 AOF 中会出现 100 个条目。其中 99 个条目不需要重建当前状态。

重写是完全安全的。当 Redis 继续追加到旧文件时,会使用创建当前数据集所需的最少操作集生成一个全新的文件,一旦第二个文件准备就绪,Redis 就会切换这两个文件并开始追加到新文件。

因此,Redis 支持一个有趣的功能:它能够在后台重建 AOF,而不会中断对客户端的服务。每当您发出 时BGREWRITEAOFopen in new window,Redis 都会写入在内存中重建当前数据集所需的最短命令序列。如果您将 AOF 与 Redis 2.2 一起使用,则需要BGREWRITEAOFopen in new window不时运行。由于Redis 2.4能够自动触发日志重写(更多信息请参见示例配置文件)。

**从Redis 7.0.0开始,当计划进行AOF重写时,Redis父进程会打开一个新的增量AOF文件来继续写入。子进程执行重写逻辑并生成新的基础 AOF。**Redis将使用临时清单文件来跟踪新生成的基础文件和增量文件。当它们准备好时,Redis将执行原子替换操作以使这个临时清单文件生效。为了避免 AOF 重写重复失败和重试时创建大量增量文件的问题,Redis 引入了 AOF 重写限制机制,以确保失败的 AOF 重写以越来越慢的速度重试。

Redis >= 7.0

  • Redis fork子进程open in new window,所以现在我们有一个子进程和一个父进程。
  • 子进程开始在临时文件中写入新的基本 AOF。
  • 父级打开一个新的增量 AOF 文件以继续写入更新。如果重写失败,旧的基本文件和增量文件(如果有)加上这个新打开的增量文件就代表了完整的更新数据集,所以我们是安全的。
  • 当子进程完成重写基本文件时,父进程收到一个信号,并使用新打开的增量文件和子进程生成的基本文件来构建临时清单,并将其保留。
  • Redis 对清单文件进行原子交换,以便 AOF 重写的结果生效。Redis 还会清理旧的基本文件和任何未使用的增量文件。

Redis < 7.0

  • Redisfork子进程open in new window,所以现在我们有一个子进程和一个父进程。
  • 子进程开始在临时文件中写入新的 AOF。
  • 父级将所有新更改累积在内存缓冲区中(但同时它将新更改写入旧的仅追加文件中,因此如果重写失败,我们是安全的)。
  • 当子进程重写完文件后,父进程会收到一个信号,并将内存缓冲区附加到子进程生成的文件的末尾。
  • 现在,Redis 以原子方式将新文件重命名为旧文件,并开始将新数据附加到新文件中。

优点

  • 您可以有不同的 fsync 策略:根本不进行 fsync、每秒进行 fsync、每次查询时进行 fsync。采用每秒fsync的默认策略,写入性能仍然很棒。fsync 是使用后台线程执行的,当没有 fsync 正在进行时,主线程将努力执行写入,因此您只能丢失一秒钟的写入。
  • AOF 日志是仅追加日志,因此不会出现查找问题,并且在断电时也不会出现损坏问题。即使由于某种原因(磁盘已满或其他原因)日志以半写命令结束,redis-check-aof 工具也能够轻松修复它。
  • 当 AOF 太大时,Redis 能够在后台自动重写 AOF。重写是完全安全的,因为当 Redis 继续追加到旧文件时,会使用创建当前数据集所需的最少操作集生成一个全新的文件,一旦第二个文件准备就绪,Redis 就会切换这两个文件并开始追加到新的那一个
  • AOF 以一种易于理解和解析的格式依次包含所有操作的日志。您甚至可以轻松导出 AOF 文件。例如,即使您不小心使用该FLUSHALLopen in new window命令刷新了所有内容,只要在此期间没有执行日志重写,您仍然可以通过停止服务器、删除最新命令并再次重新启动 Redis 来保存数据集。

缺点

  • 对于相同的数据集,AOF 文件通常比等效的 RDB 文件大。
  • AOF 可能比 RDB 慢,具体取决于确切的 fsync 策略。一般来说,将 fsync 设置为每秒一次的性能仍然非常高,并且禁用 fsync 后,即使在高负载下,它也应该与 RDB 一样快。即使在巨大的写入负载的情况下,RDB仍然能够对最大延迟提供更多的保证。

Redis < 7.0

  • 如果在重写期间对数据库进行写入(这些内容会缓冲在内存中并在最后写入新的 AOF),则 AOF 可能会使用大量内存。
  • 重写期间到达的所有写入命令都会写入磁盘两次。
  • Redis 在重写结束时冻结写入并将这些写入命令同步到新的 AOF 文件。因此可能会导致一段时间内的数据持久化能力下降。

混合持久化

Redis 4.0 中提出了一个混合使用 AOF 日志和内存快照的方法。简单来说,内存快照以一定的频率执行,在两次快照之间,使用 AOF 日志记录这期间的所有命令操作。

这样一来,快照不用很频繁地执行,这就避免了频繁 fork 对主线程的影响。而且,AOF 日志也只用记录两次快照间的操作,也就是说,不需要记录所有操作了,因此,就不会出现文件过大的情况了,也可以避免重写开销。

如果把混合持久化打开,AOF 重写的时候就直接把 RDB 的内容写到 AOF 文件开头。这样做的好处是可以结合 RDB 和 AOF 的优点, 快速加载同时避免丢失过多的数据。当然缺点也是有的, AOF 里面的 RDB 部分是压缩格式不再是 AOF 格式,可读性较差。

从持久化文件恢复数据

恢复数据
恢复数据

那么为什么会优先加载AOF呢?因为AOF保存的数据更完整,通过上面的分析我们知道AOF基本上最多损失1s的数据。