Skip to the content.

Redis 持久化

Redis 是内存数据库,一但发生断电等事故时,所有的数据都会丢失,所以 Redis 提供了两种持久化方案:RDB 快照和 AOF 日志。

持久化是指将数据写入持久化存储,例如固态硬盘 (SSD) 。

RDB 快照

RDB 快照就是将 Redis 服务器某个瞬间的状态记录下来保存到硬盘的过程。

触发机制

执行流程

image-20231121171630225

文件处理

优缺点

AOF 日志

AOF 日志就是把 Redis 服务器所处理过的每一条写命令,以文本的形式保存到硬盘的过程。

当 Redis 服务器启动时,读取这个 AOF 日志,就会重现之前执行过的每一条写命令,以达到恢复数据的目的。

AOF 日志默认是关闭的,可通过修改配置文件将其打开(将 no 修改成 yes),默认配置如下:

appendonly no

日志写回硬盘策略

AOF 日志共有三种写回硬盘的策略:

一、三两种策略相比策略二较为极端,但这些策略不分好坏,选用哪种策略,应根据实际的应用场景而定。

Redis 服务器默认采用策略二,配置如下:

# appendfsync always
appendfsync everysec
# appendfsync no

重写机制

由于 Redis 服务器会不断处理命令,所以 AOF 日志文件也会不断的变大,而较大的 AOF 文件会导致下次 Redis 服务器重启时耗时较长,并且较大的 AOF 文件中会出现很多的命令冗余(AOF 会记录每一条命令,而 AOF 日志应记录最新的服务器状态,所以 AOF 文件中会出现很多的中间命令是无效的),所以当 AOF 文件的时长/大小达到一定程度后,会根据当前 Redis 服务器的状态,重写 AOF 文件。

AOF 文件的重写分为手动触发和自动触发:

AOF 的重写流程

image-20231120213009471

为什么 fork 之后,父进程(Redis 主线程)仍然会往缓冲区里写呢?

如果子进程出现问题了然后挂了,那么此时父进程也没往缓冲区里写,于是就没往旧 AOF 文件里写,此时就会造成数据丢失。

为什么 fork 之后,父进程会多往一个 aof_rewrite_buf 缓冲区里写呢?

因为父子进程是相互隔离的,在子进程进行 AOF 操作期间,父进程处理的所有命令,子进程是感知不到的,所以需要父进程专门再为子进程 (新 AOF 文件) 准备一份缓冲区,当子进程发送信号通知父进程 AOF 已处理好时,父进程会调用相应的处理函数,将 aof_rewrite_buf 里的数据刷新到新 AOF 文件中。

Redis 服务器启动时的数据恢复流程

image-20231120214923758

混合持久化

AOF 本来就是按照文本的形式记录命令的,以恢复数据的。但随之时间与大小的增长,后续的成本还是挺高的,所以 Redis 官方又引入了混合持久化,结合了 RDB 快照和 AOF 日志的特点。当 AOF 日志进行重写时,以 RDB 快照的方式记录下当前服务器的状态并存入 AOF 文件中(依旧是二进制),当重写完毕后,还是用文本的形式记录命令。混合持久化机制默认是开启的,可通过修改配置文件进行关闭,默认配置如下:

aof-use-rdb-preamble yes

本站所有文章转发 CSDN 将按侵权追究法律责任,其它情况随意。