Redis 如果仅仅只是将数据缓存在内存里面,在Redis 宕机重启后内存里的数据就丢失了。因此必须用 redis 的持久化机制,将数据写入内存的同时,异步的慢慢的将数据写入磁盘文件里,进行持久化。redis 宕机重启,自动从磁盘上加载之前持久化数据,可以避免可能出现缓存雪崩问题。
redis 的持久化有哪几种方式
Redis支持RDB和AOF两种持久化机制,持久化功能有效地避免因进程退出造成的数据丢失问题,当下次重启时利用之前持久化的文件即可实现数 据恢复。
RDB:RDB 持久化机制,是对 redis 中的数据执行周期性的持久化。快照模式 AOF:AOF 机制对每条写入命令作为日志,以 append-only
的模式写入一个日志文件中,在 redis 重启的时候,可以通过回放 AOF 日志中的写入指令来重新构建整个数据集。
通过 RDB 或 AOF,都可以将 redis 内存中的数据给持久化到磁盘上面来,然后可以将这些数据备份到别的地方去,比如说阿里云等云服务。redis 挂了之后重新启动 ,redis 就会自动到指定的目录中根据持久化数据文件中的数据,去恢复内存中的数据,继续对外提供服务。
RDB持久化
RDB持久化是把当前进程数据生成快照保存到硬盘的过程,触发RDB持久化过程分为手动触发和自动触发m
redis的持久化依赖save和bgsave命令。bgsave是主流的触发RDB持久化方式
1.手动触发RDB的持久
save命令
优点:节约系统资源。
缺点:阻塞当前Redis进程,阻塞期间,服务器无法响应其他的处理,直到RDB过程完成为止,对于内存 比较大的实例会造成长时间阻塞,线上环境不建议使用
bgsave命令
优点:Redis进程执行fork操作创建子进程,RDB持久化过程由子进程负责,完成后自动结束。阻塞只发生在fork阶段,一般时间很短。
缺点:由于会fork一个进程,因此更消耗内存。
2.自动触发RDB的持久
使用save相关配置,如“save m n”。表示m秒内数据集存在n次修改 时,自动触发bgsave。
如果从节点执行全量复制操作,主节点自动执行bgsave生成RDB文件并发送给从节点。
执行debug reload命令重新加载Redis时,也会自动触发save操作。
默认情况下执行shutdown命令时,如果没有开启AOF持久化功能则 自动执行bgsave。
3.bgsave执行过程

执行bgsave命令,Redis父进程判断当前是否存在正在执行的子进 程,如RDB/AOF子进程,如果存在bgsave命令直接返回。 父进程执行fork操作创建子进程,fork操作过程中父进程会阻塞,通 过info stats命令查看latest_fork_usec选项,可以获取最近一个fork操作的耗时,单位为微秒 父进程fork完成后,bgsave命令返回“Background saving started”信息并不再阻塞父进程,可以继续响应其他命令。 子进程创建RDB文件,根据父进程内存数据生成临时快照文件,完成后 对原有文件进行原子替换。执行lastsave命令可以获取最后一次生成RDB的时间,对应info统计的rdb_last_save_time选项。 进程发送信号给父进程表示完成,父进程更新统计信息,具体见 info Persistence下的rdb_*相关选项。
4.RDB文件的处理
RDB文件保存在dir配置指定的目录下,文件名通过dbfilename配置指定。可以通过执行config set dir{newDir}和config set dbfilename{newFileName}运行期动态执行,当下次运行时RDB文件会保存到新目录。
5.RDB的优缺点
RDB的优点:
RDB是一个紧凑压缩的二进制文件,代表Redis在某个时间点上的数据快照。非常适用于备份,全量复制等场景。可以将这种完整的数据文件发送到一些远程的安全存储上去,用于灾难恢复。
Redis加载RDB恢复数据远远快于AOF的方式。
RDB 对 redis 对外提供的读写服务,影响非常小,可以让 redis 保持高性能,因为 redis 主进程只需要 fork 一个子进程,让子进程执行磁盘 IO 操作来进行 RDB 持久化即可。
RDB的缺点:
RDB方式数据没办法做到实时持久化/秒级持久化。因为bgsave每次运 行都要执行fork操作创建子进程,属于重量级操作,频繁执行成本过高。
RDB文件使用特定二进制格式保存,Redis版本演进过程中有多个格式 的RDB版本,存在老版本Redis服务无法兼容新版RDB格式的问题。
一般来说,RDB 数据快照文件,都是每隔 5 分钟,或者更长时间生成一次,这个时候就得接受一旦 redis 进程宕机,那么会丢失最近 5 分钟的数据。
AOF持久化
AOF持久化:以独立日志的方式记录每次写命令, 重启时再重新执行AOF文件中的命令达到恢复数据的目的。
AOF的主要作用:是解决了数据持久化的实时性,目前已经是Redis持久化的主流方式
1. AOF使用
开启AOF:需要设置配置:appendonly yes,默认不开启。
AOF文件名:通过appendfilename配置设置,默认文件名是appendonly.aof。
保存路径:同RDB持久化方式一致,通过dir配置指定。
2. AOF的工作流程
命令写入 (append) 文件同步(sync) 文件重写(rewrite) 重启加载 (load)
流程说明:
1. 所有的写入命令会追加到aof_buf(缓冲区)中。
AOF把命令追加到aof_buf中原因
Redis使用单线程响应命令,如果每次写AOF文件命令都直接追加到硬盘,那么性能完全取决于当前硬盘负载。 Redis可以提供多种缓冲区同步硬盘的策略,在性能和安全性方面做出平衡
2. AOF缓冲区根据对应的策略向硬盘做同步操作。
3. 随着AOF文件越来越大,需要定期对AOF文件进行重写,达到压缩的目的。
AOF重写降低了文件占用空间,更小的AOF 文件可以更快地被Redis加载
重写后的AOF文件可以变小原因:
进程内已经超时的数据不再写入文件。
旧AOF文件含有历史的无效命令。重写使用进程内数据直接生成,新的AOF文件只保留最终数据的写入命令。
合并多条写命令为一个,为了防止单条命令过大造成客户端缓冲区溢出,对于list、set、hash、zset等类型操作,以64个元素为界拆分为多条。
3.AOF重写
AOF重写分为手动触发和自动触发两种方式。
手动触发:直接调用bgrewriteaof命令。
自动触发:根据auto-aof-rewrite-min-size和auto-aof-rewrite-percentage参数确定自动触发时机
auto-aof-rewrite-min-size:表示运行AOF重写时文件最小体积,默认为64MB。
auto-aof-rewrite-percentage:代表当前AOF文件空间 (aof_current_size)和上一次重写后AOF文件空间(aof_base_size)的比值。
自动触发时机=aof_current_size>auto-aof-rewrite-min-size &&(aof_current_size-aof_base_size)/aof_base_size>=auto-aof-rewrite-percentage
其中aof_current_size和aof_base_size可以在info Persistence信息中查看。
4. AOF数据恢复。
当Redis服务器重启时,可以加载AOF文件进行数据恢复。
流程说明:
1)AOF持久化开启且存在AOF文件时,优先加载AOF文件,打印如下日志:
DB loaded from append only file: 5.841 seconds
2)AOF关闭或者AOF文件不存在时,加载RDB文件,打印如下日志:
DB loaded from disk: 5.586 seconds
3)加载AOF/RDB文件成功后,Redis启动成功。
4)AOF/RDB文件存在错误时,Redis启动失败并打印错误信息。
AOF 优缺点
AOF 可以更好的保护数据不丢失,一般 AOF 会每隔 1 秒,通过一个后台线程执行一次 fsync
操作,最多丢失 1 秒钟的数据。AOF 日志文件以 append-only
模式写入,所以没有任何磁盘寻址的开销,写入性能非常高,而且文件不容易破损,即使文件尾部破损,也很容易修复。AOF 日志文件即使过大的时候,出现后台重写操作,也不会影响客户端的读写。因为在 rewrite
log 的时候,会对其中的指令进行压缩,创建出一份需要恢复数据的最小日志出来。在创建新日志文件的时候,老的日志文件还是照常写入。当新的 merge 后的日志文件 ready 的时候,再交换新老日志文件即可。AOF 日志文件的命令通过非常可读的方式进行记录,这个特性非常适合做灾难性的误删除的紧急恢复。 对于同一份数据来说,AOF 日志文件通常比 RDB 数据快照文件更大。 AOF 开启后,支持的写 QPS 会比 RDB 支持的写 QPS 低,因为 AOF 一般会配置成每秒 fsync
一次日志文件,当然,每秒一次fsync
,性能也还是很高的。(如果实时写入,那么 QPS 会大降,redis 性能会大大降低)AOF 就是为了避免 rewrite 过程导致的 bug,因此每次 rewrite 并不是基于旧的指令日志进行 merge 的,而是基于当时内存中的数据进行指令的重新构建,这样健壮性会好很多。
RDB 和 AOF 到底该如何选择
不要仅仅使用 RDB,因为那样会导致丢失很多数据; 也不要仅仅使用 AOF,因为那样有两个问题: 第一,通过 AOF 做冷备,没有 RDB 做冷备来的恢复速度更快; 第二,RDB 每次简单粗暴生成数据快照,更加健壮,可以避免 AOF 这种复杂的备份和恢复机制的 bug; redis 支持同时开启开启两种持久化方式,可以综合使用 AOF 和 RDB 两种持久化机制,用 AOF 来保证数据不丢失,作为数据恢复的第一选择; 用 RDB 来做不同程度的冷备,在 AOF 文件都丢失或损坏不可用的时候,还可以使用 RDB 来进行快速的数据恢复。
总结
Redis提供了两种持久化方式:RDB和AOF。
RDB使用一次性生成内存快照的方式,产生的文件紧凑压缩比更高,因此读取RDB恢复速度更快。由于每次生成RDB开销较大,无法做到实时持久化,一般用于数据冷备和复制传输。
save命令会阻塞主线程不建议使用,bgsave命令通过fork操作创建子 进程生成RDB避免阻塞。
AOF通过追加写命令到文件实现持久化,通过appendfsync参数可以控制实时/秒级持久化。因为需要不断追加写命令,所以AOF文件体积逐渐变大,需要定期执行重写操作来降低文件体积。
AOF重写可以通过auto-aof-rewrite-min-size和auto-aof-rewritepercentage参数控制自动触发,也可以使用bgrewriteaof命令手动触发。
子进程执行期间使用copy-on-write机制与父进程共享内存,避免内存消耗翻倍。AOF重写期间还需要维护重写缓冲区,保存新的写入命令避免数据丢失。
持久化阻塞主线程场景有:
fork阻塞:fork阻塞时间 跟内存量和系统有关。 AOF追加阻塞:AOF追加阻塞说明硬盘资源紧张。




