Redis持久化

138 阅读7分钟

为什么需要持久化

目前redis应用于各互联网公司,在应用中占了不可或缺的分量。假如redis里存储了大量重要数据,突然遇到停电或者意外宕机,再启动后数据不见了,那将会产生巨大的损失,所以需要持久化数据,通过持久化文件恢复数据。

redis提供两种方式进行持久化,一种是RDB持久化(原理是将Reids在内存中的数据库记录定时dump到磁盘上的RDB持久化),另外一种是AOF(append only file)持久化(原理是将Reids的操作日志以追加的方式写入文件)。 Redis 4.0 之后推出的 RDB-AOF 混合持久化模式,其作为默认配置来使用。那么持久化方式有什么区别呢?本文将为您介绍他们的特性。

什么是RDB

RDB持久化方式能够在指定的时间间隔能对数据进行快照存储。 在默认情况下,Redis 将数据库快照保存在名字为 dump.rdb的二进制文件中。 在 Redis 运行时,RDB 程序将当前内存中的数据库快照保存到磁盘文件中, 在 Redis 重启动时,RDB 程序可以通过载入 RDB 文件来还原数据库的状态。

RDB的三种主要触发机制

save命令(同步数据到磁盘上)

save 命令执行一个同步操作,以RDB文件的方式保存所有数据的快照。

由于 save 命令是同步命令,会占用Redis的主进程。若Redis数据非常多时,save命令执行速度会非常慢,阻塞所有客户端的请求。 因此很少在生产环境直接使用SAVE 命令,可以使用BGSAVE 命令代替。如果在BGSAVE命令的保存数据的子进程发生错误的时,用 SAVE命令保存最新的数据是最后的手段。

bgsave命令(异步保存数据到磁盘上)

bgsave 命令执行一个异步操作,以RDB文件的方式保存所有数据的快照。

Redis使用Linux系统的fock()生成一个子进程来将DB数据保存到磁盘,主进程继续提供服务以供客户端调用。 如果操作成功,可以通过客户端命令LASTSAVE来检查操作结果。

自动生成RDB

除了手动执行 save 和 bgsave 命令实现RDB持久化以外,Redis还提供了自动自动生成RDB的方式。 你可以通过配置文件对 Redis 进行设置, 让它在“ N 秒内数据集至少有 M 个改动”这一条件被满足时, 自动进行数据集保存操作。 比如说, 以下设置会让 Redis 在满足“ 60 秒内有至少有 1000 个键被改动”这一条件时, 自动进行数据集保存操作。

优点

RDB是一个非常紧凑的文件,它保存了某个时间点的数据集,非常适用于数据集的备份,你可以隔段时间保存过去的数据,这样即使出了问题也可以恢复到不同版本的数据集。

RDB在保存RDB文件时父进程唯一需要做的就是fork出一个子进程,接下来的工作全部由子进程来做,父进程不需要再做其他IO操作,所以RDB持久化方式可以最大化redis的性能。

与AOF相比,在恢复大的数据集的时候,RDB方式会更快一些。

缺点

RDB方式数据没办法做到实时持久化/秒级持久化。因为bgsave每次运行都要执行fork操作创建子进程,属于重量级操作,频繁执行成本过高。

RDB文件使用特定二进制格式保存,Redis版本演进过程中有多个格式的RDB格式,存在老版本Redis服务无法兼容新版RDB格式的问题。

针对RDB不适合实时持久化的问题,Redis提供了AOF持久化方式来解决

什么是AOF

AOF是AppendOnly File的缩写,是Redis系统提供了一种记录Redis操作的持久化方案,在AOF生成的文件中,将忠实记录发生在Redis的操作,从而达到在Redis服务器重启或者当机之后,继续恢复之前数据状态的机制。

基础原理

每次都在aof文件后面追加命令。他与主进程收到请求、处理请求是串行化的,而非异步并行的。

所以aof的频率高的话绝逼会对Redis带来性能影响,因为每次都是刷盘操作。跟mysql一样了。Redis每次都是先将命令放到缓冲区,然后根据具体策略(每秒/每条指令/缓冲区满)进行刷盘操作。如果配置的always,那么就是典型阻塞,如果是sec,每秒的话,那么会开一个同步线程去每秒进行刷盘操作,对主线程影响稍小。

额外扩展

其实Redis每次在写入AOF缓冲区之前,他都会调用flushAppendOnlyFile(),判断是否需要将AOF缓冲区的内容写入和同步到AOF文件中。这个决策是由配置文件的三个策略来控制的

always everysec no

AOF重写

因为 AOF 的运作方式是不断地将命令追加到文件的末尾, 所以随着写入命令的不断增加, AOF 文件的体积也会变得越来越大。举个例子, 如果你对一个计数器调用了 100 次 INCR , 那么仅仅是为了保存这个计数器的当前值, AOF 文件就需要使用 100 条记录(entry)。然而在实际上, 只使用一条 SET 命令已经足以保存计数器的当前值了, 其余 99 条记录实际上都是多余的。 为了处理这种情况, Redis 支持一种有趣的特性:可以在不打断服务客户端的情况下, 对 AOF 文件进行重建(rebuild)。执行 bgrewriteaof 命令, Redis 将生成一个新的 AOF 文件, 这个文件包含重建当前数据集所需的最少命令。 Redis 2.2 需要自己手动执行 bgrewriteaof 命令;Redis 2.4 则可以通过配置自动触发 AOF 重写。

AOF重写的作用

减少磁盘占用量 加速数据恢复 AOF重写的实现方式

bgrewriteaof 命令 Redis bgrewriteaof 命令用于异步执行一个 AOF(AppendOnly File)文件重写操作。重写会创建一个当前AOF文件的体积优化版本。 即使 bgrewriteaof 执行失败,也不会有任何数据丢失,因为旧的AOF文件在 bgrewriteaof 成功之前不会被修改。 AOF 重写由 Redis 自行触发,bgrewriteaof 仅仅用于手动触发重写操作。 具体内容: 如果一个子Redis是通过磁盘快照创建的,AOF重写将会在RDB终止后才开始保存。这种情况下BGREWRITEAOF仍然会返回OK状态码。从Redis 2.6起你可以通过INFO命令查看AOF重写执行情况。 如果只在执行的AOF重写返回一个错误,AOF重写将会在稍后一点的时间重新调用。

优点

持久化的速度快,因为每次都只是追加,rdb每次都全量持久化 数据相对更可靠,丢失少,因可以配置每秒持久化、每个命令执行完就持久化

缺点

灾难性恢复的时候过慢,因为aof每次都只追加原命令,导致aof文件过大,但是后面会rewrite,但是相对于rdb也是慢的。 会对主进程对外提供请求的效率造成影响,接收请求、处理请求、写aof文件这三步是串行原子执行的。而非异步多线程执行的。

RDB-AOF混合持久化

当 aof-use-rdb-preamble 设置为 yes 时,表示开启 RDB-AOF 混合持久化模式。 在该模式下,AOF 重写产生的文件将同时包含 RDB 格式的内容和 AOF 格式的内容,该文件的前半段是 RDB 格式的全量数据,而后半段是 Redis 命令格式的增量数据

优点

混合持久化结合了RDB持久化 和 AOF 持久化的优点,采取了rdb的文件小易于灾难恢复,同时结合AOF,增量的数据以AOF方式保存了,数据更少的丢失。

缺点

兼容性差,一旦开启了混合持久化,在4.0之前版本都不识别该aof文件,同时由于前部分是RDB格式,需要专业的工具来阅读,因为是二进制,所以阅读性较差。