一、简介:
Redis支持RDB和AOF两种持久化机制,持久化功能有效地避免因进程退出造成的数据丢失问题,当下次重启时利用之前持久化的文件即可实现数据恢复。理解掌握持久化机制对于Redis运维非常重要。
二、RDB
1.概念:
RDB
持久化是把当前进程数据生成快照保存到硬盘的过程,触发
RDB
持久化过程分为手动触发和自动触发
2.触发机制:
2.1手动触发
(1)save命令
阻塞当前Redis服务器,直到RDB过程完成为止,对于内存 比较大的实例会造成长时间阻塞,线上环境不建议使用。
(2)bgsave命令
Redis
进程执行
fork
操作创建子进程,
RDB
持久化过程由子进程负责,完成后自动结束。阻塞只发生在fork
阶段,一般时间很短。
显然
bgsave
命令是针对
save
阻塞问题做的优化。因此
Redis
内部所有的涉 及RDB
的操作都采用
bgsave
的方式,而
save
命令已经废弃。如下图为bgsave工作流程
2.2自动触发
(1)使用
save
相关配置,如
“save m n”
。表示
m
秒内数据集存在
n
次修改时,自动触发bgsave
。
(2)如果从节点执行全量复制操作,主节点自动执行
bgsave
生成
RDB
文件并发送给从节点
(3)执行debug reload命令重新加载Redis时,也会自动触发save操作。
(4)默认情况下执行shutdown命令时,如果没有开启AOF持久化功能则自动执行bgsave。
3.RDB优缺点
RDB的优点:
(1)RDB
是一个紧凑压缩的二进制文件,代表
Redis
在某个时间点上的数据 快照。非常适用于备份,全量复制等场景。比如每6
小时执行
bgsave
备份, 并把RDB
文件拷贝到远程机器或者文件系统中(如
hdfs
),用于灾难恢复。
(2)Redis
加载
RDB
恢复数据远远快于
AOF
的方式
RDB的缺点:
(1)RDB
方式数据没办法做到实时持久化
/
秒级持久化。因为
bgsave
每次运
行都要执行
fork
操作创建子进程,属于重量级操作,频繁执行成本过高。
(2)RDB
文件使用特定二进制格式保存,
Redis
版本演进过程中有多个格式
的
RDB
版本,存在老版本
Redis
服务无法兼容新版
RDB
格式的问题。
三、AOF(append only file)持久化
1.概念
以独立日志的方式记录每次写命令, 重启时再重新执行AOF文件中的命令达到恢复数据的目的。AOF的主要作用是解决了数据持久化的实时性,目前已经是Redis持久化的主流方式
2.开启方式
开启
AOF自动触发
功能需要设置配置:
appendonly yes
,默认不开启。
AOF
文件名 通过appendfilename
配置设置,默认文件名是
appendonly.aof
。保存路径同 RDB持久化方式一致,通过
dir
配置指定
3.工作流程
1
)所有的写入命令会追加到
aof_buf
(缓冲区)中。
2
)
AOF
缓冲区根据对应的策略向硬盘做同步操作。
3
)随着
AOF
文件越来越大,需要定期对
AOF
文件进行重写,达到压缩
的目的。
4
)当
Redis
服务器重启时,可以加载
AOF
文件进行数据恢复。
4.AOF命令写入
4.1.AOF为什么直接采用文本协议格式?
(1)文本协议具有很好的兼容性。 开启AOF
后,所有写入命令都包含追加操作,直接采用协议格式,避免了二次处理开销
(2)文本协议具有可读性,方便直接修改和处理。
4.2.AOF为什么把命令追加到aof_buf中?
Redis
使用单线程响应命令,如果每次写AOF
文件命令都直接追加到硬盘,那么性能完全取决于当前硬盘负载
5.文件同步
Redis
提供了多种
AOF
缓冲区同步文件策略,由参数
appendfsync
控制
![](https://i-blog.csdnimg.cn/blog_migrate/b174c6c1eef7270816c78b7e10f9728e.png)
配置为
always
时,每次写入都要同步
AOF
文件,在一般的
SATA
硬盘 上,Redis
只能支持大约几百
TPS
写入,显然跟
Redis
高性能特性背道而驰, 不建议配置。
配置为
no
,由于操作系统每次同步
AOF
文件的周期不可控,而且会加 大每次同步硬盘的数据量,虽然提升了性能,但数据安全性无法保证。·
配置为
everysec
,是建议的同步策略,也是默认配置,做到兼顾性能和数据安全性。理论上只有在系统突然宕机的情况下丢失1
秒的数据。(严格来说最多丢失1
秒数据是不准确的,当AOF堵塞时会丢失两秒,后面会介绍
)
6.AOF文件重写机制
随着命令不断写入
AOF
,文件会越来越大,为了解决这个问题,
Redis 引入AOF
重写机制压缩文件体积。
AOF
文件重写是把
Redis
进程内的数据转化为写命令同步到新AOF
文件的过程。
6.1触发方式
(1)手动触发
使用bgrewriteaof命令:Redis主进程fork子进程来执行AOF重写,这个子进程创建新的AOF文件来存储重写结果,防止影响旧文件。因为fork采用了写时复制机制,子进程不能访问在其被创建出来之后产生的新数据。Redis使用“AOF重写缓冲区”保存这部分新数据,最后父进程将AOF重写缓冲区的数据写入新的AOF文件中然后使用新AOF文件替换老文件。
(2)自动触发:
根据
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
)的比值
6.2工作流程
![](https://i-blog.csdnimg.cn/blog_migrate/f6bf313b28ccc90caf859ef349573a20.png)
(3.1)主进程
fork
操作完成后,继续响应其他命令。所有修改命令依然写入AOF
缓冲区并根据
appendfsync
策略同步到硬盘,保证原有
AOF
机制正确性。
(3.2)
由于
fork
操作运用写时复制技术,子进程只能共享
fork
操作时的内存数据。由于父进程依然响应命令,Redis
使用
“AOF
重写缓冲区
”
保存这部分新数据,防止新AOF
文件生成期间丢失这部分数据。
(4)子进程根据内存快照,按照命令合并规则写入到新的
AOF
文件。每次批量写入硬盘数据量由配置aof-rewrite-incremental-fsync
控制,默认为32MB,防止单次刷盘数据过多造成硬盘阻塞。
(5.1)新
AOF
文件写入完成后,子进程发送信号给父进程,父进程更新统计信息,具体见info persistence
下的
aof_*
相关统计。
(5.2)父进程把
AOF
重写缓冲区的数据写入到新的
AOF
文件。
(6.2)使用新
AOF
文件替换老文件,完成
AOF
重写。
7.AOF追加堵塞
当开启
AOF
持久化时,常用的同步硬盘的策略是
everysec
,用于平衡性能和数据安全性。对于这种方式,Redis
使用另一条线程每秒执行
fsync
同步硬盘。当系统硬盘资源繁忙时,会造成Redis
主线程阻塞
![](https://i-blog.csdnimg.cn/blog_migrate/cd78b04cfcf92a38926e368c5013ed34.png)
(1)主线程负责写入
AOF
缓冲区。
(2)AOF
线程负责每秒执行一次同步磁盘操作,并记录最近一次同步时间。
(3)主线程负责对比上次
AOF
同步时间:
·
如果距上次同步成功时间在
2
秒内,主线程直接返回。
·
如果距上次同步成功时间超过
2
秒,主线程将会阻塞,直到同步操作完成。
所以fork
阻塞和
AOF
追加阻塞。
fork
阻塞时间跟内存量和系统有关,AOF
追加阻塞说明硬盘资源紧张。
每当发生
AOF
追加阻塞事件发生时,在
info Persistence
统计中,aof_delayed_fsync指标会累加,查看这个指标方便定位
AOF
阻塞问题
四、重启加载
AOF
和
RDB
文件都可以用于服务器重启时的数据恢复,流程如下:
![](https://i-blog.csdnimg.cn/blog_migrate/b5a0d106093d391eb6bc13551c900a9c.png)
AOF
持久化开启且存在
AOF
文件时,优先加载
AOF
文件,如果没有会用RDB,但是不开启AOF即便没有RDB也不会加载AOF
五、fork子进程详解
当
Redis
做
RDB
或
AOF
重写时,一个必不可少的操作就是执行
fork
操作创 建子进程,对于大多数操作系统来说fork
是个重量级错误。虽然
fork
创建的 子进程不需要拷贝父进程的物理内存空间,但是会复制父进程的空间内存页表。例如对于10GB
的
Redis
进程,需要复制大约
20MB
的内存页表,因此
fork 操作耗时跟进程总内存量息息相关
如何改善fork操作的耗时?
(1)优先使用物理机或者高效支持
fork
操作的虚拟化技术,避免使用Xen。
(2)控制
Redis
实例最大可用内存,
fork
耗时跟内存量成正比,线上建议 每个Redis
实例内存控制在
10GB
以内。
(3)合理配置Linux
内存分配策略,避免物理内存不足导致
fork失败
(4)降低
fork
操作的频率,如适度放宽
AOF
自动触发时机,避免不必要的全量复制等