目录
持久化
Redis是一个基于内存的数据库,它的数据都存储于内存当中,一旦出现服务故障或者其他原因导致服务器关机,那么它的数据也将一同消失。那么将Redis的数据也写入到磁盘当中保存,这个过程叫做数据持久化,其数据持久化功能是保证数据安全与持久性的关键。
RDB持久化
概念
RDB 持久化机制通过创建内存中数据的快照(snapshot),并将其保存到磁盘上的二进制文件中。这个文件通常称为 dump.rdb 文件。RDB 文件可以在 Redis 服务器重启时用于恢复数据。
原理
我们都知道Redis是一个单线程程序,采用IO多路复用同时负责多个客户端套接字的并发读写操作。在服务线上请求的同时,Redis还需要进行内存快照,内存快照要求必须进行文件IO操作,文件IO操作会严重降低服务请求的性能,还可能会阻塞处理线上的请求业务。为了解决这些问题,实现边持久化边处理请求,Redis使用操作系统的多进程COW(Copy On Write)机制来实现快照持久化。
Redis在持久化时会调用glibc的函数fork产生一个子进程,快照持久化完全交给子进程来处理,父进程处理客户端请求。
RDB 持久化的详细工作流程
-
1触发持久化:
- RDB 持久化可以通过手动命令(如
SAVE
或BGSAVE
)或自动配置(在配置文件中设置条件)触发。 - 当满足条件时,Redis 会启动一个快照操作。
- RDB 持久化可以通过手动命令(如
-
2创建子进程:
- Redis 通过
fork
系统调用创建一个子进程。子进程是父进程的一个副本,拥有相同的内存数据。 - 子进程负责将内存中的数据写入 RDB 文件,而父进程继续处理客户端请求。
- Redis 通过
-
3数据写入 RDB 文件:
- 子进程遍历 Redis 内存中的所有数据结构,将它们序列化并写入一个临时 RDB 文件。
- 序列化的过程将 Redis 的各种数据结构(如字符串、哈希、列表、集合、有序集合等)转换成 RDB 文件格式。
-
4替换旧文件:
- 当子进程完成数据写入后,会用新的 RDB 文件替换旧的 RDB 文件。
- 通过这种方式,确保在整个持久化过程中,磁盘上始终有一个完整且有效的 RDB 文件。
-
5回收子进程:
- 子进程完成任务后会退出,操作系统回收子进程的资源。
- 父进程通过等待子进程的退出信号,确保持久化操作成功完成。
RDB持久化的触发方式
1.手动触发:
SAVE
命令:阻塞 Redis 服务器,生成 RDB 文件。适合在非生产环境或对短暂停顿不敏感的场景使用。BGSAVE
命令:在后台生成 RDB 文件,不阻塞服务器。适用于生产环境。
2.自动触发:
- 在 Redis 配置文件
redis.conf
中配置save
选项,定义在一定时间内数据变更的次数,满足这些条件时自动生成 RDB 文件。例如:
save 900 1 # 900秒(15分钟)内至少有1个键发生变化
save 300 10 # 300秒(5分钟)内至少有10个键发生变化
save 60 10000 # 60秒(1分钟)内至少有10000个键发生变化
3.其他情况:
- 当执行
FLUSHALL
或FLUSHDB
命令时,如果开启了rdbcompression
配置,Redis 会先执行一次 RDB 持久化。
RDB持久化的优缺点
优点
- 快速重启:RDB 文件是紧凑的二进制文件,加载速度快,适合用于快速恢复大量数据。
- 性能开销低:持久化在子进程中进行,不会阻塞主进程的读写操作。
- 数据完整性高:RDB 文件包含某一时刻的全量数据,文件格式稳定可靠,适合备份和灾难恢复。
缺点
- 数据丢失风险:由于 RDB 是通过间隔一定时间创建快照,若在快照间隔期间 Redis 崩溃,则可能丢失这段时间内的数据。
- 大数据量性能问题:对于非常大的数据集,RDB 文件的生成和写入过程可能会消耗较多的系统资源。
AOF(Append Only File)持久化
原理
AOF日志 通过记录 Redis 接收到的每个写操作命令,将其追加到一个日志文件中,从而实现数据的持久化。
AOF文件的格式
AOF 文件是文本文件,按顺序记录每次写操作命令。
假设 AOF 日志记录了自 Redis 实例创建以来所有的修改性指令序列,那么就可以通过对一个空的 Redis 实例顺序执行所有的指令,也就是「重放」,来恢复 Redis 当前实例的内存数据结构的状态。
写入机制
Redis在收到客户端修改命令后,先进性响应的校验如果没问题,就立刻将该命令追加到.aof文件中,也就是先存到磁盘中,然后服务器再执行命令。如果遇到了突发的宕机情况,也只需要将存储到.aof文件中的命令运行一次,就可以恢复到宕机前的状态。
写入缓存
上述过程中,将命令的写入是一个IO操作。Redis为了提升写入效率,它不会将内容直接写入磁盘中,而是将其放到一个内存缓存区(buffer)中,等到缓存区被填满时采用异步真正将缓存区中的内容写入到磁盘里。
但是会出现一个问题就是,如果机器突然宕机,AOF日志内容可能还没有拉的及完全刷到磁盘中,这个时候就会出现日志丢失。所以Redis为数据的安全性考虑,同样为AOF持久化提供了策略配置。
AOF持久化配置
AOF默认不开启,可以在 redis.conf 文件中对AOF进行配置开启
1.开启AOF配置
appendonly yes
2.AOF文件名称
appendfilename "appendonly.aof"
3.同步策略
always
:每次写操作后立即调用fsync
,确保数据立即写入磁盘,最安全但性能最差。everysec
:每秒调用一次fsync
,性能和安全性的折中方案,推荐使用。no
:完全依赖操作系统进行同步,性能最好但数据安全性最低。
appendfsync everysec
由于是 fsync 是磁盘 IO 操作,所以它很慢!如果 Redis 执行一条指令就要 fsync 一次(Always),那么 Redis 高性能将严重受到影响。
在生产环境的服务器中,Redis 通常是每隔 1s 左右执行一次 fsync 操作( Everysec),这样既保持了高性能,也让数据尽可能的少丢失。最后一种策略(No),让操作系统来决定何时将数据同步到磁盘,这种策略存在许多不确定性,所以不建议使用。
AOF重写机制
Redis在长期运行的过程中,aof文件会越来越大。如果机器宕机重启,运行整个aof文件会非常耗时,导致长时间Redis无法对外提供服务。因此需要对aof文件做一下”瘦身运动“。
AOF重写配置
auto-aof-rewrite-percentage 100
auto-aof-rewrite-min-size 64mb
AOF 重写是减少 AOF 文件体积的重要手段。当满足以下条件之一时,Redis 会触发 AOF 重写:
- AOF 文件的大小是上次重写后的 100%(即翻倍)。
- AOF 文件的大小超过了
auto-aof-rewrite-min-size
设置的最小值。
AOF持久化的详细工作流程
1.记录写操作:
- 每当有写操作(如
SET
、LPUSH
等)执行时,Redis 会将该命令以文本形式追加到 AOF 文件末尾。
2.追加同步:
- 通过
fsync
操作,将追加的数据从缓冲区同步到磁盘,确保数据写入磁盘。 - AOF 提供三种不同的同步策略,分别是:
always
、everysec
和no
,详细见后文配置部分。
3.AOF 重写:
- 随着时间推移,AOF 文件会越来越大。为减少文件体积,Redis 提供了 AOF 重写机制。
- 重写过程生成一个新的 AOF 文件,包含当前数据库状态的最小命令集。
- 重写通过一个后台子进程完成,子进程会读取当前内存数据并将其转换为命令写入新的 AOF 文件。
4.文件替换:
- 当新的 AOF 文件生成后,Redis 会替换旧的 AOF 文件,并继续记录新的写操作。
适用场景
AOF 持久化适用于以下场景:
- 高数据安全性要求:如金融系统、交易平台等需要最小化数据丢失的场景。
- 需要可读日志:如开发调试、运维分析时需要可读的日志文件。
- 频繁写操作:适用于写操作频繁且数据变动较多的应用。
缺点
- 比RDB占用更多的磁盘空间
- 恢复备份速度要慢
- 每次读写都同步的话,有一定的性能压力
- 存在个别bug,造成不能恢复
AOF和RDB对比
RDB持久化 | AOF持久化 |
全量备份,一次保存真个数据库 | 增量备份,一次只保存一个修改数据库的命令 |
每次执行持久化操作的间隔时间较长 | 保存的间隔默认为一秒钟(Everysec) |
数据保存为二进制格式,其还原速度快。 | 使用文本格式还原数据,所以数据还原速度一般。 |
执行SAVE命令时会阻塞服务器,但手动或者自动触发的BGSAVE不会阻塞服务器 | AOF持久化无论何时都不会阻塞服务器 |
官方推荐两个都启用。
如果对数据不敏感,可以单独用RDB。
不建议单独使用AOF,因为可能会出现BUG。
如果只是做纯内存缓存,可以都不用。