前面我们介绍了Redis的数据是存储在内存中的,那么可想而知数据断电既没,那么有没有一种机制不让它没呢,那就是持久化机制❤️
持久化机制简介
- 一句话:就是将Redis中的数据以某种方式存储在磁盘上,一旦redis宕机重启,在将磁盘上的持久化文件以某种方式回写进Redis。
持久化方式
RDB持久化可以在指定的时间间隔内生成数据集的时间点快照(point-in-time snapshot)。AOF持久化记录服务器执行的所有写操作命令,并在服务器启动时,通过重新执行这些命令来还原数据集。 AOF 文件中的命令全部以 Redis 协议的格式来保存,新命令会被追加到文件的末尾。 Redis 还可以在后台对 AOF 文件进行重写(rewrite),使得 AOF 文件的体积不会超出保存数据集状态所需的实际大小。- Redis 还可以同时使用 AOF 持久化和 RDB 持久化。 在这种情况下, 当 Redis 重启时, 它会优先使用 AOF 文件来还原数据集, 因为 AOF 文件保存的数据集通常比 RDB 文件所保存的数据集更完整。
- 你甚至可以关闭持久化功能,让数据只在服务器运行时存在。
RDB介绍
- 在指定的时间间隔内将内存中的数据集
快照写入磁盘,也就是Snapshot快照,它恢复时是将快照文件直接读到内存里。 - Redis会单独创建(fork)一个子线程来进行持久化,会先将数据写到一个临时文件中,主线程是不进行任何IO操作的,这就确保了极高的性能如果需要进行大规模数据的恢复,且对于数据恢复的完整性不是非常敏感,那RDB方式要比AOF方式更加的高效。RDB的缺点是最后一次持久化后的数据可能丢失
- Fork的作用是复制一个与当前进程一样的进程。新进程的所有数据(变量,环境变量,程序计数器等)数值都和原进程一致,但是是一个全新的进程,并作为原进程的子进程。
- 在
redis.conf配置文件中存在SNAPSHOTTING,里面的内容是快照的相关配置
redis7 中rdb的触发机制变更:
-
这里有个小坑: 那就是当手动敲命令shutdown的时候,redis会迅速生成一个快照并覆盖原有的dump.rdb,这样的话如果在shutdown之前 执行了flushall命令 清空了redis,即使重启redis,那么也不会还原原有数据。 -
如何触发RDB快照:
- 配置文件中默认的快照配置
- 命令
save:这个命令只管保存,其他不管,全部阻塞。 或者是bgsave:Redis会在后台异步进行快照同时还可以响应客户端请求。可以通过lastsave命令获取最后一次成功执行快照的时间 - 执行flushall命令也会产生dump.rdb,但是里面是空的,无意义
- 如果说数据极其重要,需要写进去即刻就生成对应的dum.rdb,不能等待redis自动生成,那么可以用 save命令手动生成
-
如何通过RDB备份的文件恢复数据
- 将备份文件(默认dump.rdb)移动到redis的安装目录并启动服务即可
-
优势
- RDB 是一个非常紧凑(compact)的文件,它保存了 Redis 在某个时间点上的数据集。 这种文件非常适合用于进行备份: 比如说,你可以在最近的 24 小时内,每小时备份一次 RDB 文件,并且在每个月的每一天,也备份一个 RDB 文件。 这样的话,即使遇上问题,也可以随时将数据集还原到不同的版本。
- RDB 非常适用于灾难恢复(disaster recovery):它只有一个文件,并且内容都非常紧凑,可以(在加密后)将它传送到别的数据中心。
- RDB 可以最大化 Redis 的性能:父进程在保存 RDB 文件时唯一要做的就是
fork出一个子进程,然后这个子进程就会处理接下来的所有保存工作,父进程无须执行任何磁盘 I/O 操作。 - RDB 在恢复大数据集时的速度比 AOF 的恢复速度要快。
- 适合大规模的数据恢复,对数据的完整性和一致性要求不高
- 劣势
- 如果你需要尽量避免在服务器故障时丢失数据,那么 RDB 不适合你。 虽然 Redis 允许你设置不同的保存点(save point)来控制保存 RDB 文件的频率, 但是, 因为RDB 文件需要保存整个数据集的状态, 所以它并不是一个轻松的操作。 因此你可能会至少 5 分钟才保存一次 RDB 文件。 在这种情况下, 一旦发生故障停机, 你就可能会丢失好几分钟的数据
- 每次保存 RDB 的时候,Redis 都要
fork()出一个子进程,并由子进程来进行实际的持久化工作。 在数据集比较庞大时,fork()可能会非常耗时,造成服务器在某某毫秒内停止处理客户端; 如果数据集非常巨大,并且 CPU 时间非常紧张的话,那么这种停止时间甚至可能会长达整整一秒。 虽然 AOF 重写也需要进行fork(),但无论 AOF 重写的执行间隔有多长,数据的耐久性都不会有任何损失
AOF介绍
- AOF 持久化记录服务器执行的所有写操作命令,并在服务器启动时,通过重新执行这些命令来还原数据集。
- 是以日志的形式来记录每个写操作,将Redis执行过的所有写指令记录下来(读操作不记录),只许追加文件但不可以改写文件,redis启动之初会读取该文件重新构建数据,换言之,redis重启的话就会根据日志文件的内容将写指令从前到后执行一次以完成数据的恢复工作
- AOF保存的是appendonly.aof文件(默认)
- appendonly.aof 和dump.rdb 可以和平共存,启动之初寻找appendonly.aof,如果没有再去寻找dump.rdb来恢复数据
- 如果appendonly.aof文件出错,那么redis在启动的时候就不能成功启动。这样在redis的安装目录和redis-server 同一级有一个
redis-check-aof文件,可以通过这个文件来修复。指令:redis-check-aof --fix appendonly.aof - 配置位置
- 同步策略(appendfsync):
Always:同步持久化,每次发生数据变更会被立即记录到磁盘,性能较差,但数据完整性较好Everysec:出厂默认推荐,异步操作,每秒记录,然后记录到磁盘,如果一秒内宕机,有数据丢失。no:写入aof文件,不等待磁盘同步
- AOF启动/恢复:
- 启动:修改默认的appendonly
no为yes - 恢复:将有内容的appendonly.aof文件放到redis的安装目录下,启动的时候redis会自动找aof文件进行数据恢复
- 启动:修改默认的appendonly
- Rewrite(重写):
- 是什么:AOF采用文件追加方式,文件会越来越大为避免出现这种情况,新增了重写机制,当AOF文件的大小超过了所设定的阙值时,Redis就会启动AOF 文件的内容压缩,只保留可以恢复数据的最小指令集,可以使用命令
bgrewriteaof - 重写原理:AOF文件持续增长而过大时,会fork出一条新进程来将文件重写(也是先写临时文件最后在rename),遍历新进程的内存中数据,每条记录有一条set语句。重写aof文件的操作,并没有读取旧的aof文件,而是将整个内存中的数据库内容用命令的方式重写了一个新的aof文件,这点和快照有点类似
- 触发机制:Redis会记录上次重写时的AOF大小,默认配置是当AOF文件大小是上次rewrite后大小的一倍且文件大于64M时触发
- 是什么:AOF采用文件追加方式,文件会越来越大为避免出现这种情况,新增了重写机制,当AOF文件的大小超过了所设定的阙值时,Redis就会启动AOF 文件的内容压缩,只保留可以恢复数据的最小指令集,可以使用命令
-
优势
- 使用 AOF 持久化会让 Redis 变得非常耐久(much more durable):你可以设置不同的
fsync策略,比如无fsync,每秒钟一次fsync,或者每次执行写入命令时fsync。 AOF 的默认策略为每秒钟fsync一次,在这种配置下,Redis 仍然可以保持良好的性能,并且就算发生故障停机,也最多只会丢失一秒钟的数据(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执行之前的状态。
- 使用 AOF 持久化会让 Redis 变得非常耐久(much more durable):你可以设置不同的
-
劣势
- 对于相同的数据集来说,AOF 文件的体积通常要大于 RDB 文件的体积。
- 根据所使用的
fsync策略,AOF 的速度可能会慢于 RDB 。 在一般情况下, 每秒fsync的性能依然非常高, 而关闭fsync可以让 AOF 的速度和 RDB 一样快, 即使在高负荷之下也是如此。 不过在处理巨大的写入载入时,RDB 可以提供更有保证的最大延迟时间(latency)。 - AOF 在过去曾经发生过这样的 bug : 因为个别命令的原因,导致 AOF 文件在重新载入时,无法将数据集恢复成保存时的原样。 (举个例子,阻塞命令 BRPOPLPUSH 就曾经引起过这样的 bug 。) 测试套件里为这种情况添加了测试: 它们会自动生成随机的、复杂的数据集, 并通过重新载入这些数据来确保一切正常。 虽然这种 bug 在 AOF 文件中并不常见, 但是对比来说, RDB 几乎是不可能出现这种 bug 的。
好了,到此两种持久化机制RDB和AOF就介绍完了,两者各有特色,可以两者一起使用。🔥