Redis的持久化
持久化功能可以有效地避免因进程退出造成的数据丢失问题:当下次重启时利用之前持久化的文件即可实现数据恢复。Redis 支持 RDB(Redis DataBase)和 AOF(Append Only File)两种持久化机制
1. RDB
RDB 持久化是把当前进程数据生成的快照(SNAPSHOTTING)保存到硬盘的过程,触发 RDB 持久化过程分为手动触发和自动触发。
1.1 触发机制
1.1.1 save
阻塞当前 Redis 服务器,直到 RDB 过程完成,不建议使用。
1.1.2 bgsave
Redis 进程执行 fork 操作创建子进程,持久化过程由子进程负责(异步),阻塞只发生在 fork 阶段。
fork 的作用是复制一个与当前进程一样的进程。
新进程的所有数据(变量、环境变量、程序计数器等) 数值都和原进程一致,但是是一个全新的进程,并作为原进程的子进程.
1.1.3 自动触发
- 使用
save
进行了相关配置 - 若从主节点执行全量复制操作,主节点自动执行
bgsave
生成 rdb 文件并发送给从节点 - 执行
debug reload
命令重新加载 Redis 时,自动触发save
操作 - 默认情况下执行
shutdown
命令时,若没有开启 AOF 则自动执行bgsave
1.2 bgsave流程
- 执行
bgsave
命令,Redis 父进程判断当前是否存在正在执行的子进程,若存在则直接返回 - 父进程执行 fork 操作
- fork 完成后,
bgsave
命令返回Background saving started
信息,且不再阻塞父进程,父进程可继续响应其他命令 - 子进程创建 RDB 文件,根据父进程内存生成临时快照文件,完成后对原有文件进行原子替换
- 子进程完成操作后给父进程发送信号,父进程更新统计信息
1.3 RDB文件的处理
1.3.1 目录及名称
- 通过配置文件
dbfilename dump.rdb
dir ./
- 通过命令
CONFIG SET parameter value
config set dir newDir # 设置新的存储目录
config set dbfilename newFileName # 设置新的文件名
1.3.2 是否压缩
- 配置文件
rdbcompression yes
默认开启,使用了LZF算法,大幅降低文件体积
- 命令
config set rdbcompression yes
1.4 优缺点
1.4.1 优点
- RDB 是紧凑的二进制文件,代表 Redis 在某个时间点上的数据快照,适用于备份、全景复制等场景。
- Redis 加载 RDB 恢复数据远快于 AOF
1.4.2 缺点
- 做不到实时持久化/秒级持久化,因为 fork 操作属于重量级操作
- 新旧版本的 RDB 文件存在兼容性问题
2. AOF
AOF 持久化是以独立日志的方式记录每次写命令(只追加不该写),重启时再重新执行一遍 AOF 文件中的命令来恢复数据。
AOF 文件的存放目录与命名跟 RDB 文件类似,不再赘述。开启 AOF 需要在配置文件中进行配置 appendonly yes
Redis 4.0 开始支持 RDB 和 AOF 的混合持久化(默认关闭,可以通过配置项
aof-use-rdb-preamble
开启)。如果把混合持久化打开,AOF 重写的时候就直接把 RDB 的内容写到 AOF 文件开头。这样做的好处是可以结合 RDB 和 AOF 的优点, 快速加载同时避免丢失过多的数据。当然缺点也是有的, AOF 里面的 RDB 部分是压缩格式不再是 AOF 格式,可读性较差。
2.1 AOF 流程
- 所有的写命令会追加到 aof-buf(缓冲区)中
- AOF 缓冲区根据对应的策略向硬盘做同步操作
- 随着 AOF 文件越来越大,需要定期对 AOF 文件进行重写,达到压缩目的
- Redis 服务器重启后,可以加载 AOF 文件进行数据恢复
2.2 append
AOF 命令写入的内容是文本协议格式
2.3 sync
Redis 提供了多种 AOF 缓冲区同步文件策略,在配置文件中通过 appendfsync
参数进行配置,具体如下:
-
always
命令写入缓冲区后立即调用系统 fsync 操作同步到 AOF 文件中,性能较差但数据完整性较好
-
everysec
命令写入缓冲区后每秒调用一次系统 fsync 操作同步到 AOF 文件中,可能丢失本秒钟的数据
-
no
命令写入缓冲区后由操作系统决定多久调用一次系统 fsync 操作同步到 AOF 文件中(通常最长30秒)
2.4 rewrite
2.4.1 重写
AOF 重写机制可以压缩文件体积(如合并多条写命令),AOF 重写过程可以手动触发和自动触发:
- 手动触发:调用
bgrewriteaof
命令 - 自动触发:根据配置文件中的
auto-aof-rewrite-percentage 100
和auto-aof-rewrite-min-size 64mb
参数确定触发时机。
2.4.2 重写流程
-
执行
bhrewriteaof
重写请求若当前进程正在执行
bhrewriteaof
,请求不执行直接返回;若当前进程正在执行
bgsave
操作,命令延迟到bgsave
完成后再执行 -
父进程执行 fork 创建子进程
-
接下来分为两步:
- 主进程继续响应其他命令,所有修改命令写入 aof_buf 缓冲区并根据 appendsync 策略同步到硬盘
- fork 操作运用写时复制技术,子进程只能共享 fork 操作时的内存数据。由于父进程依然响应命令,Redis 使用 aof_rewrite_buf 缓冲区保存这部分新数据,防止新 AOF 文件生产期间丢失这部分数据
-
子进程根据内存快照,按照命令合并规则写入到新的 AOF 文件
-
接下来分为三步:
- 新 AOF 文件写入完成后,子进程给父进程发送信号,父进程更新统计信息
- 父进程把 aof_rewrite_buf 缓冲区的数据写入到 AOF 文件
- 使用新的 AOF 文件替换掉旧的,完成重写
2.5 load
AOF 和 RDB 同时开启时,优先加载 AOF 文件。