redis持久化方式

2021/07/23

官网地址:官网地址 当前翻译官网地址

Redis四种持久化方式:

  • RDB(Redis Database): RDB在指定时间间隔内,持久化数据集时间点的快照。
  • AOF(Append Only File):AOF持久化记录服务器收到的每一个写操作,启动的时候再次执行这些操作,重建原始数据集。命令被记录使用与Redis协议本身相同的格式,以一种只追加的方式。当日志变得太大时,Redis能够在后台重写日志。
  • 禁用持久化:如果你愿意,您可以完全禁用持久性,如果您希望您的数据只在服务器运行时存在。
  • RDB+AOF:在同一个实例中是可能联合RDB和AOF的,注意,在这种情况下,当Redis重新启动AOF文件将被用来重建原始数据集,因为它是最完整的。

RDB优势

  • RDB是Redis数据的一个非常紧凑的单文件时间点表示。RDB文件是完美的备份。例如,你可能在最近24小时内每个小时对RDB文件进行归档,并每天保存一个RDB快照,持续30天。这允许您在发生灾难时轻松恢复数据集的不同版本。
  • RDB非常适合灾难后恢复,因为它是一个可以传输到远端数据中心或Amazon S3(可能是加密的)的压缩文件。
  • RDB最大化Redis的性能,父进程仅仅需要做的工作就是foking一个子进程,父进程绝不会执行磁盘IO或者类似的操作。
  • 与AOF相比,RDB允许在大数据集下更快地重启。
  • 对于副本,RDB支持重启和故障转移后的部分重同步。副本

RDB劣势

  • 如果你需要在Redis停止工作(例如断电)的情况下最小化数据丢失的机会,RDB是不好的。您可以在生成RDB的地方配置不同的保存点(例如在至少5分钟并对数据集进行100次写操作之后,但是您可以有多个保存点)。然而,你通常会每5分钟或更长的时间创建一个RDB快照,所以在Redis停止工作没有正确关闭的任何原因,你应该准备丢失最新的几分钟的数据。
  • 为了使用子进程在磁盘上持久化,RDB经常需要fork()。如果数据集很大,Fork()可能会很耗时,如果数据集很大,CPU性能不佳,可能会导致Redis停止服务客户几毫秒甚至一秒。AOF还需要fork(),但您可以调整重写日志的频率,而不需要在持久性上做出任何权衡。

AOF优势

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

AOF劣势

  • 对于同样的数据集,AOF文件通常比等效的RDB文件大。
  • AOF可能比RDB慢,取决于准确的fsync策略。一般来说,把fsync设置到每秒,性能仍然很高,禁用fsync,它将会和RDB一样快,即使在高负载的情况下。 即使在写负载很大的情况下,RDB仍然能够提供关于最大延迟的更多保证。
  • 在过去,我们在特定的命令中遇到过罕见的错误(例如,有一个涉及到像BRPOPLPUSH这样的阻塞命令),这导致AOF在重新加载时不能精确地复制相同的数据集。 这些错误很少见,我们在测试套件中进行了测试,自动创建随机复杂的数据集,并重新加载它们以检查一切是否正常。然而,在RDB持久性中几乎不可能出现这类错误。为了更清楚地说明这一点:Redis AOF通过增量更新现有状态来工作,就像MySQL或MongoDB一样,

怎样使用它们?

一般情况下,如果您想要与PostgreSQL提供的数据安全性相媲美的数据安全性,就应该同时使用这两种持久性方法。

如果你非常关心你的数据,在发生灾难时仍然能容忍几分钟的数据丢失,你能够简单的只使用RDB。

许多用户单独使用AOF,但是我们不鼓励这样做,因为时不时的使用RDB做数据备份、快速重启、 在AOF引擎出现bug的情况下时都是一个好主意。

注意:由于所有这些原因,我们可能最终会在未来(长期计划)将AOF和RDB统一为一个单一的持久性模型。

以下举例阐述更多的细节关于两种持久化方式

快照

默认情况下,Redis将数据集的快照保存在一个名为dump.rdb的二进制文件中。你可以配置Redis,让它每N秒保存数据集,如果数据集有至少M的变化,或者你可以手动调用save或BGSAVE命令。 例如,这个配置将使Redis自动转储数据集到磁盘每60秒,如果至少1000个键改变:

save 60 1000

这种策略被称为快照。 它怎样工作 每当Redis需要转储数据集到磁盘,这是发生:

  • Redis forks,我们现在有一个子进程和父进程。
  • 子进程开始写数据集到一个临时RDB文件
  • 当子进程完成写新的RDB文件,它会替换旧的RDB文件。 这种方法使Redis受益于“写即拷贝”的语义

    Append-only file

    快照不是很持久,如果你运行的Redis停止了,你的电线坏了,或者你意外的kill -9应用实例,写在Redis最新的数据将会丢失。虽然这对某些应用程序来说可能不是什么大问题,有完全耐用性的用例,在这些情况下Redis不是一个可行的选择。

对于Redis来说,AOF是一种替代的、完全持久的策略。它在1.1版中可用。 你可以在配置文件中打开AOF:

appendonly yes

从现在开始,每次Redis收到一个命令,改变数据集(例如SET),它将追加到AOF。当你重启Redis时,它会重新播放AOF来重建状态。

日志重写

可以猜到,随着写操作的执行,AOF会越来越大。例如,如果您将一个计数器递增100次,那么您将在数据集中使用包含最终值的单个键,但在您的AOF中有100个条目。重建当前状态不需要其中的99项。 所以Redis支持一个有趣的特性:它能够在不中断对客户端的服务的情况下在后台重建AOF。每当您发出BGREWRITEAOF Redis将写入所需的最短命令序列重建当前数据集在内存中。如果你在Redis 2.2中使用AOF,你需要时不时地运行BGREWRITEAOF。Redis 2.4能够自动触发日志重写(更多信息,请参阅2.4示例配置文件)。

怎样持久AOF?(How durable is the append only file?)

你能够配置Redis多久fsync一次数据到磁盘,这里有三种可选。

  • appendfsync 总是:每次在AOF追加新命令时,执行fsync命令,非常非常慢,非常安全。注意,命令是在执行来自多个客户端或管道的一批命令之后追加到AOF的,所以这意味着一次写入和一次fsync(在发送应答之前)。
  • appendfsync 每秒:fsync每秒,足够快(在2.4版本中可能和快照的方式一样快),如果发生灾难,你可能会丢失一秒中的数据。
  • appendfsync 不:绝不fsync,把你的数据交给操作系统。这是一种更快、更不安全的方法。通常Linux会使用这个配置每30秒刷新一次数据,但这取决于内核的精确调优。 建议的(也是默认的)策略是每秒进行fsync。它既快又安全。always策略在实践中非常慢,但它支持组提交,所以如果有多个并行写操作,Redis会尝试执行一个fsync操作。 ### 如果我的AOF被截断了怎么办? 有可能是服务器在写入AOF文件时崩溃了,或者在写入AOF文件时存储的卷已经满了。当这种情况发生时,AOF仍然包含表示给定时间点版本的数据集的一致数据(使用默认的AOF fsync策略,该数据集可能在一秒内是旧的),但是AOF中的最后一个命令可能被截断。 Redis的最新主要版本无论如何都可以加载AOF,只是丢弃文件中最后一个格式不正确的命令。在这种情况下,服务器将发出如下日志: ```

  • Reading RDB preamble from AOF file…
  • Reading the remaining AOF tail…

    !!! Warning: short read while loading the AOF file !!!

    !!! Truncating the AOF at offset 439 !!!

    AOF loaded anyway because aof-load-truncated is enabled

 在这种情况下,如果你愿意,你可以改变默认配置来强制Redis停止,但默认配置是继续执行,不管文件中的最后一个命令是否格式良好,以确保重启后的可用性。
#### 旧版本的Redis可能无法恢复,可能需要以下步骤:
- 把你的AOF文件备份一份。
+ 修复原始文件使用Redis自带的Redis -check-aof工具:`$ redis-check-aof --fix`
-  也可以使用diff -u来检查两个文件之间的区别。
* 使用修复的文件重启服务。
### 如果我获得的AOF文件是损坏的,能怎么做?
如果AOF文件不仅被截断,而且中间有无效的字节序列,那么事情就会更加复杂。Redis会在启动时抱怨,并会中止:
  • Reading the remaining AOF tail…

    Bad file format reading the append only file: make a backup of your AOF file, then use ./redis-check-aof –fix

``` 最好的方法是运行redis-check-aof实用程序,最初不带——fix选项,然后了解问题,跳转到文件中给定的偏移量,看看是否有可能手动修复文件:AOF使用与Redis协议相同的格式,手动修复非常简单。否则,可以让工具为我们修复文件,但在这种情况下,从无效部分到文件末尾的所有AOF部分都可能被丢弃,如果损坏发生在文件的初始部分,则会导致大量数据丢失。

它是如何工作的

日志重写使用与快照中使用的写时复制相同的技巧。它是这样工作的:

  • Redis fork,所以我们有一个父进程和一个子进程。
  • 子进程开始在临时文件中写入AOF。
  • 父程序将所有新更改累积到内存缓冲区中(但同时它将新更改写入旧的AOF文件中,因此如果重写失败,我们是安全的)。
  • 当子进程完成重写文件时,父进程将获得一个信号,并将内存中的缓冲区附加到子进程生成的文件的末尾。
  • 有益于!现在Redis自动将旧文件重命名为新文件,并开始将新数据追加到新文件中。

    怎样切换到AOF,如果我当前使用的是dump.rdb 快照

    在Redis 2.0和Redis 2.2中有一个不同的过程,你可以猜到它在Redis 2.2中更简单,而且根本不需要重启。

    Redis >= 2.2

  • 备份最新的dump.rdb文件
  • 把这些备份文件转移到安全的地方
  • 发出以下两条命令:
  • redis-cli config set appendonly yes
  • redis-cli config set save “”
  • 确保您的数据库包含与它包含的键数相同的键。
  • 确保写是正确的附加到AOF文件 第一个CONFIG命令启用“仅追加文件”。为了做到这一点,Redis将阻塞生成初始转储,然后将打开文件写,并将开始追加所有下一个写查询。

第二个CONFIG命令用于关闭快照持久性。这是可选的,如果您愿意,可以同时启用这两个持久化方法。

注意:记住编辑您的redis.conf以打开AOF,否则当您重新启动服务器时,配置更改将丢失,服务器将以旧配置重新启动。

Redis 2.0

  • 备份最新的dump.rdb文件
  • 把这些备份文件转移到安全的地方
  • 停止对数据库的所有写操作!
  • 发出redis-cli BGREWRITEAOF命令。这将创建AOF文件。
  • 当Redis完成生成AOF转储时停止服务器。
  • 编辑 redis.conf 文件启用AOF持久化
  • 重启服务
  • 确保你数据库包含的key数量和redis包含的key数量相同
  • 确保写操作是正确的附加到AOF文件

AOF和RDB持久性之间的交互

在Redis >= 2.4 版本,