两种持久化机制
约 2479 字大约 8 分钟
2025-01-15
1.为什么有持久化
由于Redis的数据都存放在内存中,如果没有配置持久化,redis重启后数据就全丢失了,于是需要开启redis的持久化功能,将数据保存到磁盘上,当redis重启后,可以从磁盘中恢复数据。
Redis提供两种持久化方式,RDB(Redis DataBase缩写快照)和AOF(Append Only File);
第一种是RDB快照,第二种是AOF日志。
- RDB:
- RDB快照是一次全量备份
- 快照是内存数据的二进制序列化形式,在存储上非常紧凑
- AOF:
- AOF是连续的增量备份。
- AOF 日志记录的是内存数据修改的指令记录文本
2.RDB机制
2.1 定义
- RDB快照就是把数据以快照的形式保存在磁盘上,是某个时间点的一次全量数据备份,以二进制序列化形式的文件存储,并且在存储上非常紧密。
- RDB持久化是指在指定的时间间隔内将内存中的数据集以快照的方式写入磁盘,并保存到一个名为dump.rdb的二进制文件中
- RDB是默认的持久化方式,它恢复时是将快照文件从磁盘直接读到内存里
2.2 RDB触发机制
RDB来说持久化触发机制有三种:save、bgsave、自动化触发
1、save命令触发
- 该命令会阻塞当前Redis服务器,执行save命令期间,Redis不能处理其他命令,直到RDB完成为止
2、bgsave命令触发
- 执行bgsave命令时,Redis主进程会fork一个子进程来完成RDB的过程,会先将数据写入到一个临时二进制文件中,待持久化过程都结束了,再用这个临时文件替换上次持久化好的文件(可以理解为Copy On Write机制)。
- Redis主进程阻塞时间只有fork阶段的那一下。相对于save,阻塞时间很短。基本上 Redis 内部所有的RDB操作都是采用 bgsave 命令。
- fork的作用是复制一个与当前进程一样的进程。新进程的所有数据(变量、环境变量、程序计数器等)数值都和原进程一致,但是是一个全新的进程,并作为原进程的子进程。
3、自动触发
自动触发是可以在redis.conf配置文件中修改,默认达到 以下三种条件,就会自动触发持久化,触发后,底层调用的其实还有bgsave命令:
举例:1分钟内改了1万次,5分钟内改了10次,或15分钟内改了1次。
- save 900 1 #在900秒(15分钟)之后,如果至少有1个key发生变化,则dump内存快照。
- save 300 10 #在300秒(5分钟)之后,如果至少有10个key发生变化,则dump内存快照。
- save 60 10000 #在60秒(1分钟)之后,如果至少有10000个key发生变化,则dump内存快照。
如果不需要持久化机制,则可以注释掉所有的save命令
2.3 bgsave执行流程
- 执行bgsave命令的时候,Redis主进程会检查是否有子进程在执行RDB/AOF持久化任务,如果有的话,直接返回,防止两个进程同时对磁盘进行写入操作
- Redis主进程fork一个子进程来执行执行RDB操作,fork操作会对主进程造成阻塞(影响Redis的读写),fork操作完成后会发消息给主进程,从而不再阻塞主进程
- RDB子进程把Redis主进程的内存数据,写入到一个临时的快照文件,持久化完成后,再使用临时快照文件替换掉原来的RDB文件。(该过程中主进程的读写不受影响,但Redis的写操作不会同步到主进程的主内存中,而是会写到一个临时的内存区域作为一个副本)
- 子进程完成RDB持久化后会发消息给主进程,通知RDB持久化完成,并将步骤3中的内存副本中的增量写数据同步到主内存
2.4 优缺点
优点:
- RDB文件紧凑,全量备份,非常 适合用于进行备份和灾难恢复。
- 对于大规模数据的恢复,且对于数据恢复的完整性不是非常敏感的场景,RDB的恢复速度要比AOF方式更加的高效。
- 生成RDB文件的时候,redis主进程会fork()一个子进程来处理所有保存工作,主进程不需要进行任何磁盘IO操作。
缺点:
- 占用空间大:fork的时候,内存中的数据被克隆了一份,大致2倍的膨胀性需要考虑。
- 当进行快照持久化时,会开启一个子进程专门负责快照持久化,子进程会拥有父进程的内存数据,父进程修改内存子进程不会反应出来,所以在快照持久化期间修改的数据不会被保存,可能丢失数据。
- 在一定间隔时间做一次备份,所以如果redis意外down掉的话,就会丢失最后一次快照后的所有修改。
3.AOF机制
3.1 定义
- 每次都使用RDB机制全量备份的方式是非常耗时间的,因此Redis还提供了另一种持久化机制 AOF(append only file)。
- AOF日志是持续增量的备份,将Redis执行过的每个 写操作以日志的形式记录下来 (读操作不记录),只许追加文件但不可以改写文件(appendonly.aof文件)。
- redis启动的时候会读取该文件进行数据恢复,根据日志文件的内容将写指令从前到后执行一次以完成数据的恢复工作。
3.2 AOF触发机制
- 每修改同步:appendfsync always 同步持久化,每次发生数据变更会被立即记录到磁盘,性能较差但数据完整性比较好。
- 每秒同步:appendfsync everysec 异步操作,每秒记录,如果一秒内宕机,有数据丢失。
- 不同步:appendfsync no 从不同步
3.3 优点
优点:
- 数据安全,AOF持久化可以配置 appendfsync 属性,有always属性,每进行一次命令操作就记录到AOF文件中一次;
- 通过append模式写文件,即使中途服务器宕机 ,可以通过 redis-check-aof 工具解决数据一致性问题;
- AOF机制的rewrite模式。AOF文件没被 rewrite 之前(文件过大时会对命令 进行合并重写),可以删除其中的某些命令(比如误操作的 flushall);
缺点:
- AOF文件比RDB文件大,且恢复速度慢;
- 数据集大的时候,比RDB启动效率低;
注:如果同时开启两种持久化方式,在这种情况下,当redis重启的时候会优先载入AOF文件来恢复原始的数据,因为在通常情况下AOF文件保存的数据集要比RDB文件保存的数据集要完整。
4.Redis4.0的混合持久化(待理解)
- 仅使用 RDB快照方式恢复数据,由于快照时间粒度较大时,会丢失大量数据。
- 仅使用 AOF重放方式 恢复数据,日志性能相对 rdb 来说要慢。在 Redis 实例很大的情况下,启动需要花费很长的时间。
为了解决这个问题,Redis4.0开始支持RDB和AOF的混合持久化(默认关闭,可以通过配置项 aof-use-rdb-preamble 开启)。RDB 文件的内容和增量的 AOF 日志文件存在一起,这里的 AOF 日志不再是全量的日志,而是自持久化开始到持久化结束的这段时间发生的增量 AOF 日志,通常这部分 AOF 日志很小
- 大量数据使用粗粒度(时间上)的rdb快照方式,性能高,恢复时间快。
- 增量数据使用细粒度(时间上)的AOF日志方式,尽量保证数据的不丢失。
在Redis重启时,进行AOF重写的时候就直接把RDB的内容写到 AOF 文件开头。这样做的好处是可以结合 RDB和 AOF 的优点,快速加载同时避免丢失过多的数据。当然缺点也是有的, AOF 里面的 RDB 部分是压缩格式不再是AOF 格式,可读性较差。
另外,可以使用下面这种方式:Master使用AOF,Slave使用RDB快照,master需要首先确保数据完整性,它作为数据备份的第一选择;slave提供只读服务或仅作为备机,它的主要目的就是快速响应客户端read请求或灾切换。
5.RDB与AOF对比
RDB | AOF | |
---|---|---|
定义 | RDB持久化,是将内存中的数据以快照的形式保存在磁盘上,是某个时间点的一次全量数据备份 | AOF日志是持续增量的备份,将Redis执行过的每个 写操作,记录到appendonly.aof日志 |
触发机制 | save、bgsave、自动触发(redis.conf设置) | appendfsync always、appendfsync everysec、appendfsync no |
优点 | 性能高(恢复时间快)、文件占磁盘小(每次覆盖) | 数据安全 |
缺点 | 数据不安全、占用内存 | 文件占磁盘大(追加),恢复时间慢 |
适用场景 | 适用全量数据、大规模数据备份恢复 | 适用敏感数据 |
- AOF文件比RDB更新频率高,优先使用AOF还原数据;
- AOF比RDB更安全也更大;
- RDB性能比AOF好;
- 如果两个都配了优先加载AOF;