Redis的持久化

概述

https://redis.io/topics/persistence

此页面提供了Redis持久性的技术说明,它是所有Redis用户的建议读物。有关Redis持久性的更广泛概述以及它提供的持久性保证。

Redis持久性

Redis提供了不同的持久性选项:

  • RDB持久性以指定的时间间隔执行数据集的时间点快照。
  • AOF持久性记录服务器接收的每个写入操作,将在服务器启动时再次播放,重建原始数据集。使用与Redis协议本身相同的格式以仅追加方式记录命令。当Redis太大时,Redis能够重写日志背景。
  • 如果您愿意,只要服务器正在运行,您就可以根据需要禁用持久性。
  • 可以在同一实例中组合AOF和RDB。请注意,在这种情况下,当Redis重新启动时,AOF文件将用于重建原始数据集,因为它保证是最完整的。

RDB

概述

RDB(Redis DataBase),即Redis的数据库文件,将Reids在内存中的数据库记录定时dump到磁盘上的RDB持久化。在Redis上默认保存在bin目录下的dump.rdb,如在/usr/local/redis/bin下有一个dump.rdb文件。

RDB持久化是指在指定的时间间隔内将内存中的数据集快照写入磁盘,实际操作过程是fork一个子进程,先将数据集写入临时文件,写入成功后,再替换之前的文件,用二进制压缩存储。

RDB的优势

  • RDB是Redis数据的一个非常紧凑的单文件时间点表示。RDB文件非常适合备份。例如,您可能希望在最近24小时内每小时归档您的RDB文件,并且每天保存RDB快照30天。这使您可以在发生灾难时轻松恢复数据集的不同版本。

  • RDB非常适合灾难恢复, 可以将单个压缩文件传输到远端数据中心,也可以传输到Amazon S3 (可能是加密的)。

  • RDB最大限度地提高了Redis的性能,因为Redis父进程为 了坚持不懈而需要做的唯一工作就是分配一 个将完成所有其余工作的孩子。父实例永远不会执行磁盘I/O或类似操作。

  • 与AOF相比,RDB允许使用大数据集更快地重启。

RDB的缺点

  • 如果您需要在Redis停止工作时(例如断电后)将数据丢失的可能性降至最低,则RDB并不好。您可以配置生成RDB的不同保存点(例如,在对数据集进行至少五分钟和100次写入之后,但您可以有多个保存点)。但是,您通常每五分钟或更长时间创建一个RDB快照,因此如果Redis因任何原因停止工作而没有正确关闭,您应该准备丢失最新的数据分钟。

  • RDB经常需要 fork() 才能使用子进程持久存储在磁盘上。如果数据集很大,Fork() 可能会非常耗时,并且如果数据集非常大且CPU性能不佳,可能会导致Redis停止服务客户端几毫秒甚至一秒钟。 AOF也需要 fork() , 但你可以调整你想要重写日志的频率而不需要对耐久性进行任何权衡。

在指定的时间间隔内将内存中的数据集快照写入磁盘, 也就是snapshot快照,它恢复时是将快照文件直接读到内存里。

Redis会单独创建(fork)一个子进程来进行持久化,会先将数据写入到 一个临时文件中,待持久化过程都结束了,再用这个临时文件替换上次持久化好的文件。 整个过程中,主进程是不进行任何IO操作的,这就确保了极高的性能 如果需要进行大规模数据的恢复,且对于数据恢复的完整性不是非常敏感,那RDB方 式要比AOF方式更加的高效。RDB的缺点是最后一次持久化后的数据可能丢失。

Fork的作用是复制一个与当前进程一样的进程。新进程的所有数据(变量、环境变量、程序计数器等) 数值都和原进程一致,但是是一个全新的进程,并作为原进程的子进程。

三种主要触发RDB的机制

save同步命令

  • 生成 RDB 文件,会使客户端的命令排队,
  • 文件策略:如果存在老的 RDB 文件会被替换;
  • 时间复杂度:O(n);
  • 执行flushall命令,也会产生dump.rdb文件,但里面是空的,无意义

bgsave异步命令

  • 调用 Linux 的 fork() 函数创建子进程用于生成 RDB 文件;
  • 文件策略:如果存在老的 RDB 文件会被替换;
  • 时间复杂度:O(n);

自动触发

  • 在某些条件满足时,自动触发 RDB 文件的生成,以 bgsave 方式,比如:

    • save 60 10000 在 60s 内更新 10000 条数据,触发 RDB;
    • save 300 10 在 300s 内更新 10 条数据,触发 RDB;
    • save 900 1 在 900s 内更新 1 条数据,触发 RDB;
  • 相关命令

    dbfilename dump.rdb
    dir ./
    stop-writes-on-bgsave-error yes
    rdbcompression yes
    rdbchecksum yes #采用校验和的方式验证文件的完整性
    

恢复数据

将备份文件 (dump.rdb) 移动到 redis 安装目录并启动服务即可。

127.0.0.1:6379> config get dir #获取目录
1) "dir"
2) "/usr/local/redis/bin"

优点:适合大规模的数据恢复、对数据完整性和一致性要求不高。

缺点:在一定间隔时间做一次备份,所以如果redis意外down掉的话,就会丢失最后一次快照后的所有修改;Fork的时候,内存中的数据被克隆了一份,大致2倍的膨胀性需要考虑。

AOF

概述

AOF是将Reids的操作日志以追加的方式写入文件。

AOF持久化以日志的形式记录服务器所处理的每一个写、删除操作,查询操作不会记录,以文本的方式记录,可以打开文件看到详细的操作记录。

AOF保存的是appendonly.aof文件

AOF的优势

  • 该机制可以带来更高的数据安全性,即数据持久性。Redis中提供了3中同步策略,即每秒同步、每修改同步和不同步。事实上,每秒同步也是异步完成的,其效率也是非常高的,所差的是一旦系统出现宕机现象,那么这一秒钟之内修改的数据将会丢失。而每修改同步,我们可以将其视为同步持久化,即每次发生的数据变化都会被立即记录到磁盘中。可以预见,这种方式在效率上是最低的。至于无同步,无需多言,我想大家都能正确的理解它。

  • 由于该机制对日志文件的写入操作采用的是append模式,因此在写入过程中即使出现宕机现象,也不会破坏日志文件中已经存在的内容。然而如果我们本次操作只是写入了一半数据就出现了系统崩溃问题,不用担心,在Redis下一次启动之前,我们可以通过redis-check-aof工具来帮助我们解决数据一致性的问题。

  • 如果日志过大,Redis可以自动启用rewrite机制。即Redis以append模式不断的将修改数据写入到老的磁盘文件中,同时Redis还会创建一个新的文件用于记录此期间有哪些修改命令被执行。因此在进行rewrite切换时可以更好的保证数据安全性。

  • AOF包含一个格式清晰、易于理解的日志文件用于记录所有的修改操作。事实上,我们也可以通过该文件完成数据的重建。

AOF的缺点

  • 对于相同数量的数据集而言,AOF文件通常要大于RDB文件。RDB 在恢复大数据集时的速度比 AOF 的恢复速度要快。

  • 根据同步策略的不同,AOF在运行效率上往往会慢于RDB。总之,每秒同步策略的效率是比较高的,同步禁用策略的效率和RDB一样高效。

AOF启动/修复/恢复

正常恢复

启动:设置Yes,修改默认的appendonly no,改为yes。

将有数据的aof文件复制一份保存到对应目录(config get dir)。

恢复:重启redis然后重新加载。

异常恢复

启动:设置Yes 修改默认的appendonly no,改为yes

备份被写坏的AOF文件

修复: Redis-check-aof --fix进行修复

恢复:重启redis然后重新加载

优势

每修改同步:appendfsync always ,同步持久化,每次发生数据变更会被立即记录到磁盘,性能较差但数据完整性比较好。

每秒同步:appendfsync everysec ,异步操作,每秒记录。如果一秒内宕机,有数据丢失

不同步:appendfsync no :从不同步。

劣势

相同数据集的数据而言aof文件要远大于rdb文件,恢复速度慢于rdb。

aof运行效率要慢于rdb,每秒同步策略效率较好,不同步效率和rdb相同。

开发选择

官方建议

通常的指示是,如果您想要某种与PostgreSQL可以提供的功能相当的数据安全性,则应同时使用两种持久性方法。

如果您非常关心数据,但是在灾难情况下仍然可以承受几分钟的数据丢失,则可以只使用RDB。

有许多用户单独使用AOF,但我们不建议这样做,因为不时拥有RDB快照对于进行数据库备份,加快重启速度以及AOF引擎中存在错误是一个好主意。

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

自己理解及处理方式

RDB持久化方式能够在指定的时间间隔能对你的数据进行快照存储。

AOF持久化方式记录每次对服务器写的操作,当服务器重启的时候会重新执行这些 命令来恢复原始的数据,AOF命令以redis协议追加保存每次写的操作到文件末尾. Redis还能对AOF文件进行后台重写,使得AOF文件的体积不至于过大。

只做缓存:如果你只希望你的数据在服务器运行的时候存在,你也可以不使用任何持久化方式。

同时开启两种持久化方式

在这种情况下,当redis重启的时候会优先载入AOF文件来恢复原始的数据,因为在通常情况下AOF文件保存的数据集要比RDB文件保存的数据集要完整。

RDB的数据不实时,同时使用两者时服务器重启也只会找AOF文件。那要不要只使用AOF呢?建议不要,因为RDB更适合用于备份数据库(AOF在不断变化不好备份),快速重启,而且不会有AOF可能潜在的bug,留着作为一个万一的手段。

性能建议

因为RDB文件只用作后备用途,建议只在Slave上持久化RDB文件,而且只要15分钟备份一次就够了,只保留save 900 1这条规则。

如果Enalbe AOF,好处是在最恶劣情况下也只会丢失不超过两秒数据,启动脚本较简单只load自己的AOF文件就可以了。代价一是带来了持续的IO,二是AOF rewrite的最后将rewrite过程中产生的新数据写到新文件造成的阻塞几乎是不可避免的。只要硬盘许可,应该尽量减少AOF rewrite的频率,AOF重写的基础大小默认值64M太小了,可以设到5G以上。默认超过原大小100%大小时重写可以改到适当的数值。

如果不Enable AOF ,仅靠Master-Slave Replication 实现高可用性也可以。能省掉一大笔IO也减少了rewrite时带来的系统波动。代价是如果Master/Slave同时倒掉,会丢失十几分钟的数据,启动脚本也要比较两个Master/Slave中的RDB文件,载入较新的那个。新浪微博就选用了这种架构。

posted @ 2020-11-03 15:59  coydone  阅读(195)  评论(0编辑  收藏  举报