Redis持久化

Redis持久化

Redis提供了2种不同的持久化方法来将数据存储到硬盘里: 快照(RDB文件)和只追加文件(AOF文件)

  • RDB持久化方式会以特定的时间间隔保存时间点的数据快照。
  • AOF持久化方式会记录服务器收到的每个写操作,这样的话,当服务器重启,redis会逐条执行这些写操作,从而重建原来的redis数据。写操作的命令以只读,redis协议的格式被记录。当AOF文件太大的时候,Redis可以以background的方式重写此文件。
  • Redis可以禁用持久化功能,缓存的生命周期随服务器。
  • 可以在Redis里同时启用RDB和AOF持久化功能。值得注意的是,当服务重启的时候,AOF以其高完整性被用于重建原来的redis数据。

RDB优点

  • RDB是Redis数据的一个非常紧凑的单文件时间点表示。RDB文件非常适合备份。例如,您可能希望在最近24小时内每小时归档您的RDB文件,并且每天保存RDB快照30天。
    这使您可以在发生灾难时轻松恢复不同版本的数据集。
  • RDB非常适合灾难恢复,可以将单个压缩文件传输到远端数据中心,也可以传输到Amazon S3(可能是加密的)。
  • RDB最大限度地提高了Redis的性能,主进程会fork一个子进程,主进程继续处理服务请求,子进程处理文件I/O备份。
  • 与AOF相比,RDB允许使用大数据集更快地重启。

RDB缺点

  • RDB不适用于那些对数据完整性要求高的应用。假如因为停电导致服务器挂了,那么redis会丢失上次执行RDB持久化后的所有数据。可以设置不同的配置来执行RDB持久化,比如对redis进行5分钟和300次写入就执行一次RDB持久化,可以同时配置不同持久化策略。不管如何配置RDB持久化策略,当服务器因为非正常关闭时,都会丢失上次快照到出现问题时间内的数据。
  • RDB经常需要fork一个子进程来持久化数据到磁盘上。当Redis数据特别大的时候,fock子进程也会很耗时,出现redis停顿。如果数据非常大并且CPU不是很好,可能会导致Redis停止服务客户端几毫秒甚至一秒钟。AOF持久化也会fork子进程,但是可以控制重写日志的频率,不会影响主进程的服务。

AOF优点

  • AOF做redis持久化更为可靠,可以使用不同的fsync策略:不进行fsync,每秒一次fsync,每次查询进行fsync。默认采取每秒一次fsync对AOF文件进行同步,性能和不使用任何redis持久化功能时的性能相差无几。通过每秒一次fsync,redis可以保证,即使系统故障,用户最多丢失1秒之内的数据。
  • AOF日志文件是一个纯追加的文件。就算是遇到突然停电的情况,也不会出现日志的定位或者损坏问题。甚至如果因为某些原因(例如磁盘满了)命令只写了一半到日志文件里,我们也可以用redis-check-aof这个工具很简单的进行修复。
  • 当AOF文件太大时,Redis会自动在后台进行重写。重写很安全,因为重写是在一个新的文件上进行,同时Redis会继续往旧的文件追加数据。新文件上会写入能重建当前数据集的最小操作命令的集合。当新文件重写完,Redis会把新旧文件进行切换,然后开始把数据写到新文件上。
  • AOF把操作命令以简单易懂的格式一条接一条的保存在文件里,很容易导出来用于恢复数据。例如我们不小心用FLUSHALL命令把所有数据刷掉了,只要文件没有被重写,我们可以把服务停掉,把最后那条命令删掉,然后重启服务,这样就能把被刷掉的数据恢复回来。

AOF缺点

  • 对同样的redis数据集,AOF文件常常比RDB文件大。
  • 在某些fsync策略下,AOF文件会比RDB文件慢。通常情况下采用每秒一次fsync会有很高的性能,不采用fsync策略的性能和RDB相差无几。
  • 在过去曾经发现一些罕见的bug导致redis使用AOF文件重建的时候,数据不一致的问题。

那么,我们该如何选择呢?

迹象表明,如果你想redis数据安全性一定程度上和PostgreSQL可为你提供的数据安全性相当,就同时使用这两种持久化方法:RDB,AOF。

如果你care你的数据,又能容忍几分钟数据的丢失,你可以只使用RDB。

需多人都仅仅使用AOF持久化,但是不鼓励这样做,RDB可以快照某个时间点的数据,可以用于数据备份,快速重建数据,或者AOF引擎出现bug。

注意:基于以上的原因,我们可能在未来的某一时刻统一RDB和AOF到一个单一的持久化模型里。

快照

默认情况下,Redis将数据集的快照保存在磁盘上,名为dump.rdb的二进制文件中。可以配置每N秒至少有M个更改时,执行快照操作。或者主动调用SAVE or BGSAVE命令。

eg: 这个配置会使redis每60秒如果有1000次更改,自动快照redis数据,保存为dump文件。

1
save 60 1000

工作原理

当redis准备持久化数据到磁盘时候,将会发生如下步骤:

  1. Redis fork一个子进程。此时存在父进程和子进程。
  2. 子进程开始写数据集到一个临时RDB文件。
  3. 当子进程写完所有数据后,用这个临时RDB文件替换旧的RDB文件。

此方法使Redis受益于COW语义。

Append-only file

快照不是很可靠。如果运行redis实例的机器挂了,电源停电了,或者一不小心使用kill -9删除了实例,那么最新的数据将会丢失。这对某些应用可能是无伤大雅,对数据要求高的来说,redis就不是一个很好的选择。

仅附加文件是Redis的另一种完全持久的策略,可以通过配置启用AOF:

1
appendonly yes

从现在开始,每次Redis收到更改数据集的命令(例如SET)时,它都会将其附加到AOF。
当您重新启动Redis时,它将重新播放AOF以重建状态。

日志重写

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

So Redis支持重写日志文件,以background的形式压缩AOF文件。

可靠性

可以通过配置Redis fsync数据到磁盘的频率来提高可靠性,有下面三个选项:

  • 每当有新命令追加到AOF的时候调用fsync。速度最慢,但是最安全。
  • 每秒fsync一次。速度快(2.4版本跟快照方式速度差不多),安全性不错(最多丢失1秒的数据)。
  • 从不fsync,交由系统去处理。这个方式速度最快,但是安全性一般。

推荐使用每秒fsync一次的方式(默认的方式),因为它速度快,安全性也不错。

数据损坏修复

可能存在因为服务器崩溃导致AOF文件不可用,可以通过以下方式进行修复。

  • 备份AOF文件
  • 使用redis-check-aof工具修复原始的AOF文件

    1
    redis-check-aof --fix
  • 可以使用diff -u命令看下两个文件的差异

  • 使用修复过的文件重启Redis服务

工作原理

日志重写和快照一样采用COW(copy-on-write),原理如下:

  • Redis fork一个子进程
  • 子进程开始把AOF写到临时文件
  • 主进程持续把新的变动写到内存里的buffer,同时也会把这些新的变动写到旧的AOF里,这样即使重写失败也能保证数据的安全
  • 当子进程完成文件的重写后,主进程会获得一个信号,然后把内存里的buffer追加到子进程生成的那个新AOF里
  • Redis原子性重命名新文件,然后把新的数据appending新文件里

从RDB切换到AOF

Redis >= 2.2

  • 备份一个最新的dump.rdb文件,并存到一个安全的位置。
  • 执行下面2个命令:

    1
    2
    redis-cli config set appendonly yes
    redis-cli config set save ""
  • 确保数据跟切换前一致

  • 确保数据正确的写到AOF文件里

第一条命令用来启用AOF持久化,Redis会卡顿,初始化AOF文件,然后接受客户端命令并appending到AOF。

第二条命令用来关闭RDB持久化,这是可选的,你可以同时启用RDB和AOF。

别忘了更新redis.conf文件的配置,开启AOF功能,否则,当redis服务重启的时候,会继续使用旧的配置运行服务。

AOF和RDB互动

Redis> = 2.4确保在RDB快照操作正在进行时避免触发AOF重写,或者在AOF重写正在进行时允许BGSAVE。这可以防止两个Redis后台进程同时执行大量磁盘I / O.

当快照正在进行并且用户使用BGREWRITEAOF明确请求日志重写操作时,服务器将回复一个OK状态代码,告诉用户操作已安排,并且一旦快照完成,重写将开始。

在启用AOF和RDB持久性并且Redis重新启动的情况下,AOF文件将用于重建原始数据集,因为它保证是最完整的。

备份Redis数据

时刻备份你的数据!!

建议:

  • 创建一个定时任务,把当天每小时的快照放在同一个文件夹下,每天的快照放在不同的文件夹下。
  • 定时任务运行时,删除太旧的快照,比如每小时的保留最近48小时的,每天的保留最近2个月的。
  • 每天确保一次把RDB文件传送到安全的地方保存,至少不是运行redis实例的那台机器。

参考文章