Redis的两种持久化机制及其优缺点:

一、Redis 持久化:

Redis 提供了两种级别的持久化方式:

  1. RDB 持久化(快照)可以在指定的时间间隔内生成数据集的时间点快照(point-in-time snapshot)。默认文件名:dump.rdb
  2. AOF 持久化记录服务器执行的所有写操作命令,并在服务器启动时,通过重新执行这些命令来还原数据集。 AOF 文件中的命令全部以 Redis 协议的格式来保存,新命令会被追加到文件的末尾。默认文件名:appendonly.aof
  3. Redis 还可以同时使用 AOF 持久化和 RDB 持久化。 在这种情况下,当 Redis 重启时,它会优先使用 AOF 文件来还原数据集,因为AOF文件保存的数据集通常比 RDB 文件所保存的数据集更完整。
  4. 你甚至可以关闭持久化功能,让数据只在服务器运行时存在。(注意:由于Redis的数据都存放在内存中,如果没有配置持久化,redis重启后数据就会全部丢失。
    本地redis安装目录

二、RDB 快照:

在默认情况下, Redis 将数据库快照保存在名字为 dump.rdb 的二进制文件中。
你可以对 Redis 进行设置, 让它在“ N 秒内数据集至少有 M 个改动”这一条件被满足时, 自动保存一次数据集。
比如说, 以下设置会让 Redis 在满足“60秒内有至少有 1000 个键被改动”这一条件时,自动保存一次数据集:

# 注意,这里是both and的关系,只有两者同时满足时才会触发保存操作
save 60 1000

这种持久化方式被称为快照(snapshot)
本地运行举例:
配置文件:
redis配置文件redis服务端输出举例:
redis服务端日志输出
当然了,你也可以通过调用 SAVE (同步保存)或者 BGSAVE(异步保存) , 手动让 Redis 进行数据集保存操作。
一般来说,在生产环境很少执行 SAVE 操作,因为它会阻塞所有客户端,保存数据库的任务通常由 BGSAVE 命令异步地执行。然而,如果负责保存数据的后台子进程不幸出现问题时, SAVE 可以作为保存数据的最后手段来使用。
redis的save命令
BGSAVE 命令执行之后立即返回 OK ,然后 Redis fork 出一个新子进程,原来的 Redis 进程(父进程)继续处理客户端请求,而子进程则负责将数据保存到磁盘,然后退出。
在这里插入图片描述

三、RDB持久化机制:

在Redis运行时,RDB程序将当前内存中的数据库快照保存到磁盘文件中,在Redis重启动时,RDB程序可以通过载入RDB文件来还原数据库的状态。RDB机制最主要的就是rdbSaverdbLoad函数,前者将redis内存中数据加载到磁盘上,后者将在Redis重启时将数据恢复到redis内存中,注意rdbSave会阻塞主进程。


SAVEBGSAVE 两个命令都会调用rdbSave函数,但它们调用的方式各有不同:
1, SAVE 直接调用rdbSave,阻塞Redis主进程,直到保存完成为止。在主进程阻塞期间,服务器不能处理客户端的任何请求。
2,BGSAVE 则fork出一个子进程,子进程负责调用rdbSave ,并在保存完成之后向主进程发送信号,通知保存已完成。因为rdbSave 在子进程被调用,所以Redis 服务器在BGSAVE 执行期间仍然可以继续处理客户端的请求。


四、快照的运作方式:

当 Redis 需要保存 dump.rdb 文件时,服务器执行以下操作:

  1. Redis 调用 fork() ,同时拥有父进程和子进程。
  2. 子进程将数据集写入到一个临时 RDB 文件中。
  3. 当子进程完成对新 RDB文件的写入时,Redis 用新 RDB 文件替换原来的 RDB 文件,并删除旧的 RDB 文件。

这种工作方式使得 Redis 可以从写时复制(copy-on-write)机制中获益。
问题:“父进程在保存 RDB 文件时唯一要做的就是 fork 出一个子进程,然后这个子进程就会处理接下来的所有保存工作,父进程无须执行任何磁盘I/O操作。” 请问一下,在子进程执行保存的过程中是否也处理了客户端发来的请求?
:在本地做了个测试,子进程只执行保存操作(只保存 开始 到 子进程触发保存时间点的数据),不接受客户端的请求。即:在子进程执行持久化保存数据的时候,来自客户端的新数据子进程不会保存。

五、RDB 持久化的优点:

  • RDB 是一个非常紧凑的二进制文件(.rdb文件),它保存了 Redis 在某个时间点上的数据集。 这种文件非常适用于进行数据备份。比如说,你可以在最近的 24 小时内,每小时备份一次 RDB 文件,并且在每个月的每一天,也备份一个 RDB 文件。 这样的话,即使遇上问题,也可以随时将数据集还原到不同的版本。
  • RDB 非常适用于灾难恢复(disaster recovery):它只有一个文件,并且内容都非常紧凑,可以(在加密后)将它传送到别的数据中心,或者亚马逊 S3 中。
  • RDB 可以最大化 Redis 的性能:父进程在保存 RDB 文件时唯一要做的就是 fork 出一个子进程,然后这个子进程就会处理接下来的所有保存工作,父进程无须执行任何磁盘 I/O 操作。
  • RDB 在恢复大数据集时的速度比 AOF 的恢复速度要快

六、RDB 持久化的缺点:

  • 如果你需要尽量避免在服务器故障时丢失数据,那么 RDB 不适合你。 虽然 Redis 允许你设置不同的保存点(save point)来控制保存 RDB 文件的频率, 但是,因为RDB 文件需要保存整个数据集的状态, 所以它并不是一个轻松的操作。 因此你可能会至少 5 分钟才保存一次 RDB 文件。 在这种情况下, 一旦发生故障停机, 你就可能会丢失好几分钟的数据。
  • 每次保存 RDB 的时候,Redis 都要 fork() 出一个子进程,并由子进程来进行实际的持久化工作。 在数据集比较庞大时, fork() 可能会非常耗时,造成服务器在某某毫秒内停止处理客户端; 如果数据集非常巨大,并且 CPU 时间非常紧张的话,那么这种停止时间甚至可能会长达整整一秒。 虽然 AOF 重写也需要进行 fork() ,但无论 AOF 重写的执行间隔有多长,数据的耐久性都不会有任何损失。

七、AOF持久化机制的启用:

在Redis的配置文件中开启如下设置:

appendonly yes        // yes:启用aof持久化方式

appendfsync always    // 每次收到写命令就立即强制写入磁盘,最慢的,但是保证完全的持久化,不推荐使用
appendfsync everysec  // 每秒钟强制写入磁盘一次,在性能和持久化方面做了很好的折中,推荐,默认
appendfsync no        // 完全依赖操作系统,性能最好,持久化没保证,强烈不推荐

从现在开始, 每当 Redis 执行一个改变数据集的命令时(比如 SET), 这个命令就会被追加到 AOF 文件的末尾。这样的话, 当 Redis 重新启时, 程序就可以通过重新执行 AOF 文件中的命令来达到重建数据集的目的。
redis客户端
.aof文件内容举例

八、AOF 的优点:

  • 使用 AOF 持久化会让 Redis 变得非常耐久(much more durable):你可以设置不同的 fsync(同步) 策略,比如无 fsync ,每秒钟一次 fsync ,或者每次执行写入命令时 fsync 。 AOF 的默认策略为每秒钟 fsync 一次,这种 fsync 策略可以兼顾速度和安全性,并且就算发生故障停机,也最多只会丢失一秒钟的数据( fsync 会在后台线程执行,所以主线程可以继续处理命令请求)。
  • AOF 文件是一个只进行追加操作的日志文件(append only log), 因此对 AOF 文件的写入不需要进行 seek , 即使日志因为某些原因而包含了未写入完整的命令(比如写入时磁盘已满,写入中途停机,等等), redis-check-aof 工具也可以轻易地修复这种问题。
  • Redis 可以在 AOF 文件体积变得过大时,自动地在后台对 AOF 进行重写: 重写后的新 AOF 文件包含了恢复当前数据集所需的最小命令集合。 整个重写操作是绝对安全的,因为 Redis 在创建新 AOF 文件的过程中,会继续将命令追加到现有的 AOF 文件里面,即使重写过程中发生停机,现有的 AOF 文件也不会丢失。 而一旦新 AOF 文件创建完毕,Redis 就会从旧 AOF 文件切换到新 AOF 文件,并开始对新 AOF 文件进行追加操作。
  • AOF 文件有序地保存了对数据库执行的所有写入操作, 这些写入操作以 Redis 协议的格式保存, 因此 AOF 文件的内容非常容易被人读懂, 对文件进行分析(parse)也很轻松。 导出(export) AOF 文件也非常简单: 举个例子, 如果你不小心执行了 FLUSHALL 命令, 但只要 AOF 文件未被重写, 那么只要停止服务器, 移除 AOF 文件末尾的 FLUSHALL 命令, 并重启 Redis , 就可以将数据集恢复到 FLUSHALL 执行之前的状态。

解释 FLUSHALL:清空整个 Redis 服务器的数据(删除所有数据库的所有 key)


九、AOF 重写机制:

  1. aof 的方式也同时带来了另一个问题。.aof持久化文件会变的越来越大。(例如我们调用incr test命令100次,文件中必须保存全部的100条命令,其实有99条都是多余的。因为要恢复数据库的状态其实文件中保存一条set test 100就够了。)
  2. 为了压缩aof的持久化文件。redis提供了bgrewriteaof命令。收到此命令redis将使用与快照类似的方式将内存中的数据 以命令的方式保存到临时文件中,最后替换原来的文件。
    注意:从 Redis 2.4 开始, AOF 重写由 Redis 自行触发, BGREWRITEAOF 命令仅仅用于手动触发重写操作。

十、AOF 重写具体过程如下:

  1. redis调用fork(),现在有父子两个进程。
  2. 子进程执行重写工作(即:根据内存中的数据库快照,往临时文件中写入重建数据库状态的命令)
  3. 在子进程执行重写操作的同时,父进程继续处理来自客户端(client)的请求,除了把新的写命令继续追加到原来的aof文件中之外,同时将其暂存到内存缓存中。这样就能保证如果子进程重写失败的话,现有的 AOF 文件也还是安全的。
  4. 当子进程完成重写工作后,子进程发信号通知父进程。然后父进程把缓存的写命令也追加到临时文件中。
  5. 至此,重写工作结束,Redis 用新aof文件替换旧aof文件,之后所有命令都会直接追加到新 AOF 文件的末尾。

  • 需要注意到是重写aof文件的操作,并没有读取旧的aof文件,而是将整个内存中的数据库内容用命令的方式重写了一个新的aof文件,这点和快照有点类似。
  • AOF重写之后,Redis 将生成一个新的 AOF 文件, 这个文件包含重建当前数据集所需的最少命令,从而达到压缩.aof持久化文件的目的。

十一、AOF 的缺点:

  1. 对于相同的数据集来说,AOF 文件的体积通常要大于 RDB 文件的体积。
  2. 根据所使用的 fsync 策略,AOF 的速度可能会慢于 RDB 。 在一般情况下, 每秒 fsync 的性能依然非常高, 而关闭 fsync 可以让 AOF 的速度和 RDB 一样快, 即使在高负荷之下也是如此。 不过在处理巨大的写入载入时,RDB 可以提供更有保证的最大延迟时间(latency)。
  3. AOF 在过去曾经发生过这样的 bug : 因为个别命令的原因,导致 AOF 文件在重新载入时,无法将数据集恢复成保存时的原样。 (举个例子,阻塞命令 BRPOPLPUSH 就曾经引起过这样的 bug 。) 测试套件里为这种情况添加了测试: 它们会自动生成随机的、复杂的数据集, 并通过重新载入这些数据来确保一切正常。 虽然这种 bug 在 AOF 文件中并不常见, 但是对比来说, RDB 几乎是不可能出现这种 bug 的。

十二、RDB 和 AOF,我应该用哪一个?

  • 一般来说, 如果想达到足以媲美 PostgreSQL 的数据安全性,你应该同时使用两种持久化功能。
  • 如果你非常关心你的数据, 但仍然可以承受数分钟以内的数据丢失, 那么你可以只使用 RDB 持久化。
  • 有很多用户都只使用 AOF 持久化, 但我们并不推荐这种方式: 因为定时生成 RDB 快照(snapshot)非常便于进行数据库备份, 并且 RDB 恢复数据集的速度也要比 AOF 恢复的速度要快, 除此之外, 使用 RDB 还可以避免之前提到的 AOF 程序的 bug 。
    因为以上提到的种种原因, 未来我们可能会将 AOF 和 RDB 整合成单个持久化模型。 (这是一个长期计划。)

十三、怎么从 RDB 持久化切换到 AOF 持久化:

在 Redis 2.2 或以上版本,可以在不重启的情况下,从 RDB 切换到 AOF :

  1. 为最新的 dump.rdb 文件创建一个备份。
  2. 将备份放到一个安全的地方。
  3. 执行以下两条命令:
redis-cli> CONFIG SET appendonly yes
redis-cli> CONFIG SET save ""
  1. 确保命令执行之后,数据库的键的数量没有改变。
  2. 确保写命令会被正确地追加到 AOF 文件的末尾。
  • 步骤 3 执行的第一条命令开启了 AOF 功能: Redis 会阻塞直到初始 AOF 文件创建完成为止, 之后 Redis 会继续处理命令请求, 并开始将写入命令追加到 AOF 文件末尾。
  • 步骤 3 执行的第二条命令用于关闭 RDB 功能。 这一步是可选的,如果你愿意的话,也可以同时使用 RDB 和 AOF 这两种持久化功能。
  • 别忘了在 redis.conf 中打开 AOF 功能! 否则的话,服务器重启之后,之前通过 CONFIG SET 设置的配置就会被遗忘, 程序会按原来的配置来启动服务器。

十四、备份 Redis 数据:

在阅读这个小节前, 先将下面这句话铭记于心: 一定要备份你的数据库!
磁盘故障, 节点失效, 诸如此类的问题都可能让你的数据消失不见, 不进行备份是非常危险的。
Redis 对于数据备份是非常友好的, 因为你可以在服务器运行的时候对 RDB 文件进行复制: RDB 文件一旦被创建, 就不会进行任何修改。 当服务器要创建一个新的 RDB 文件时, 它先将文件的内容保存在一个临时文件里面, 当临时文件写入完毕时, 程序才使用 rename(2) 原子地用临时文件替换原来的 RDB 文件。
这也就是说,无论何时,复制 RDB 文件都是绝对安全的。
以下是我们的建议:

  • 创建一个定期任务(cron job), 每小时将一个 RDB 文件备份到一个文件夹, 并且每天将一个 RDB 文件备份到另一个文件夹。
  • 确保快照的备份都带有相应的日期和时间信息, 每次执行定期任务脚本时, 使用 find 命令来删除过期的快照: 比如说, 你可以保留最近 48 小时内的每小时快照, 还可以保留最近一两个月的每日快照。
  • 至少每天一次,将 RDB 备份到你的数据中心之外, 或者至少是备份到你运行 Redis 服务器的物理机器之外。
    这样的话,即使遇上问题,也可以随时将数据集还原到不同的版本。

特别推荐网站:菜鸟教程: https://www.runoob.com/
相关资源,Redis 命令参考:http://doc.redisfans.com/
参考url1-官网翻译文档:http://doc.redisfans.com/topic/persistence.html
参考url2-csdn作者:https://blog.csdn.net/u011784767/article/details/76824822

  • 1
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 3
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值