云计算、AI、云原生、大数据等一站式技术学习平台

网站首页 > 教程文章 正文

Redis持久化AOF和RDB的区别,分别解决什么场景的问题?

jxf315 2025-05-15 18:40:33 教程文章 1 ℃

关于Redis持久化

redis 提供了两种持久化的方式,分别是RDB(Redis DataBase)和AOF(Append Only File)。

  • 什么是RDB:就是在不同的时间点,将 redis 存储的数据生成快照并存储到磁盘等介质上
  • 什么是AOF:将 redis 执行过的所有写指令记录下来,在下次 redis 重新启动时,只要把这些写指令从前到后再重复执行一遍,就可以实现数据恢复了
  • 注意:Redis官网推荐同时使用两种方法实现持久化

Redis持久化之RDB:

redis 在进行数据持久化的过程中,会先将数据写入到一个临时文件中,待持久化过程都结束了,才会用这个临时文件替换上次持久化好的文件

根据RDB的自动触发策略自动对数据库做一次遍历,把内存快照写在一个叫做“dump.rdb”的文件里,这个持久化机制(RDB)功能叫做SNAPSHOT(snapshot:快照)。默认的dump文件( dump.rdb )是保存在 redis 服务启动时当前所在的路径下。 这样安装多个 redis 后,如果在同一个路径下启动服务,会导致 dump 文件数据错误。

默认指定存储至本地数据库时是否压缩数据,默认为 yes,Redis 采用 LZF 压缩,如果为了节省 CPU 时间,可以关闭该选项,但会导致数据库文件变的巨大

如果需要进行大规模数据的恢复,且对于数据恢复的完整性不是非常敏感,那 RDB 方式要比 AOF 方式更加的高效。

虽然 RDB 有不少优点,但它的缺点也是不容忽视的。如果你对数据的完整性非常敏感,那么 RDB 方式就不太适合你,因为即使你每 5 分钟都持久化一次,当 redis 故障时,仍然会有近 5 分钟的数据丢失。所以,redis 还提供了另一种持久化方式,那就是 AOF。

自动触发RDB:

按照redis.conf里配置的 save <seconds> <changes>:指定在多长时间内,有多少次更新操作,就将数据同步到数据文件,可以多个条件配合

1.Redis默认配置文件中提供了三个条件:(只要三个条中任意一个被满足,服务器就会执行BGSAVE)
save 900 1      表示:900秒(15分钟)内有个更改
save 300 10     表示:300秒(5分钟)内有10个更改
save 60 10000   表示:60秒内有10000个更改
如果需要关闭自动触发:只需要将配置文件修改为save "" 即可
2.修改dump文件的保存路径:默认路径为 dir./   
--->可修改为如:dir/myredis/dumpfiles(文件夹不能为空,建议修改后重启Redis)   

恢复Reids的数据:将备份的文件(dump.rdb)移动到Redis的安装目录并启动服务即可(不可以把备份文件dump.rdb和生产Redis服务器放在同一台机器,必须分开各自存储,防止生产机物理损坏后备份文件也挂了)

手动触发RDB:

  • save和bgsave命令
    • save :用于执行同步保存操作,把 Redis 实例中某一时点的所有数据的快照以 RDB 文件的形式保存到磁盘上。(生产环境不要执行 SAVE 命令,因为这会阻塞所有其它的客户端。可以使用 BGSAVE 代替。尽管如此,BGSAVE 也有执行失败的危险,SAVE 是转存最新数据集的最好也是最后一个方法。)
redis 127.0.0.1:6379> SAVE 
    • bgsave:父进程继续提供服务以供客户端调用,fork()一个子进程将DB数据保存到磁盘然后退出。客户端可以通过 lastsave命令查看相关信息,判断 BGSAVE 命令是否执行成功。
      • fork():在Linux程序中:fork()会产生一个和父进程完全相同的子进程,但子进程在此后悔exec系统调用,处于效率考虑,尽量避免膨胀

RDB恢复数据:

cp dump.rdb dump.rdb.bak    //备份dump.rdb,之后删除
rm -rf dump.rdb
mv dump.rdb.bak dump.rdb

RDB 的优点:

  1. RDB是一种表示某个即时点的Redis数据的紧凑文件。RDB文件适合用于备份。如果需要进行大规模数据的恢复,且对于数据恢复的完整性不是非常敏感,那RDB 方式要比AOF 方式更加的高效
  2. RDB最大化了Redis的性能,因为Redis父进程持久化时唯一需要做的是启动(fork)一个子进程,由子进程完成所有剩余工作。父进程实例不需要执行像磁盘IO这样的操作。
  3. RDB在重启保存了大数据集的实例时比AOF要快。

RDB的缺点:可能丢失部分数据,

  1. 当你需要在Redis停止工作(例如停电)时最小化数据丢失,RDB可能不太好。你可以配置不同的保存点(save point)来保存RDB文件(例如,至少5分钟和对数据集100次写之后,但是你可以有多个保存点)。然而,你通常每隔5分钟或更久创建一个RDB快照,所以一旦Redis因为任何原因没有正确关闭而停止工作,你就得做好最近几分钟数据丢失的准备了。
  2. RDB需要经常调用fork()子进程来持久化到磁盘。如果数据集很大的话,fork()比较耗时,结果就是,当数据集非常大并且CPU性能不够强大的话,Redis会停止服务客户端几毫秒甚至一秒。AOF也需要fork(),但是你可以调整多久频率重写日志而不会有损(trade-off)持久性(durability)

Redis持久化之AOF:

AOF,英文是 Append Only File,即只允许追加不允许改写的文件。(当开启RedisAOF时,重启Redis它会优先使用 AOF 文件来还原数据集

AOF 方式是将执行过的写指令记录下来,在数据恢复时按照从前到后的顺序再将指令都执行一遍。

AOF 保存的文件是'appendonly.aof' 文件,在Redis7以前RDB和AOF的持久化文件都是保存在Redis根目录下的。但是Redis7以后AOF的文件会在Redis根目录下创建一个appendonlydir目录来保存AOF文件其中有三个aof文件



开启AOF

通过配置 redis.conf 中的 appendonly yes 就可以打开 AOF 功能。如果有写操作(如 SET 等),redis 就会被追加到 AOF 文件的末尾



AOF的工作流程:



  1. 客户端作为命令来源,会有多个源头以及源源不断的请求命令
  2. 在这些命令达到Redis Server 以后并不是直接写入AOF文件,会将这些命令先放入AOF缓存中进行保存(实际上是内存中的一片区域,存在的目的是当这些命令达到一定量以后在写入磁盘,避免频繁IO操作
  3. AOF缓冲有三种持久化策略,将命令写入磁盘上的AOF文件
  4. 随着写入的AOF内容增加,为避免文件膨胀,会根据规则进行文件重写,从而起到文件压缩的目的
  5. 通过文件进行回写读取数据

AOF 持久化策略(写回策略):

通过修改配置文件改变AOF持久化策略:

  1. always:同步回写,每个命令执行完成后立即同步将日志写回磁盘
  2. everysec:默认的。默认的 AOF 持久化策略是每秒钟 fsync 一次
  3. no:操作系统控制的写回。

默认的 AOF 持久化策略是每秒钟 fsync 一次(fsync 是指把缓存中的写指令记录到磁盘中),因为在这种情况下,redis 仍然可以保持很好的处理性能,即使 redis 故障,也只会丢失最近 1 秒钟的数据。如果在追加日志时,恰好遇到磁盘空间满、inode 满或断电等情况导致日志写入不完整,也没有关系,redis 提供了 redis-check-aof 工具,可以用来进行日志修复

AOF 文件重写(rewrite)机制:

当 AOF 文件的大小超过所设定的阈值时,redis 就会启动 AOF 文件的内容压缩,只保留可以恢复数据的最小指令集。在进行 AOF 重写时,仍然是采用先写临时文件,全部完成后再替换的流程,所以断电、磁盘满等问题都不会影响 AOF 文件的可用性

例如:假如我们调用了 100 次 INCR 指令,在 AOF 文件中就要存储 100 条指令,但这明显是很低效的,完全可以把这 100 条指令合并成一条 SET 指令,这就是重写机制的原理,或者重新清理过期的Key

重写的触发

AOF重写过程可以手动触发和自动触发:

  • 手动触发: 直接调用bgrewriteaof命令。(命令:redis-cli bgrewriteaof)
  • 自动触发: 根据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) 的比值。(根据当前AOF文件大小比上次文件大小增长了一倍)
    • 自动触发时机为:aof_current_size > auto-aof-rewrite-minsize && (aof_current_size-aof_base_size) / aof_base_size >= auto-aof-rewritepercentage(现在的AOF文件大小大于重写前的文件大小,并且当前文件大小减去重写文件大小然后除以重写文件大小的值大于所设阈值)
      • 其中aof_current_size和aof_base_size可以在info persistence统计信息中查看。(注意:只有开启了AOF才能看到这两个参数)

重写的流程



1)执行AOF重写请求

如果当前进程正在执行AOF重写, 请求不执行并返回如下响应:

ERR Background append only file rewriting already in progress

如果当前进程正在执行bgsave操作, 重写命令延迟到bgsave完成之后再执行, 返回如下响应:

Background append only file rewriting scheduled

2)父进程执行fork创建子进程, 开销等同于bgsave过程

3)主进程fork操作完成后, 继续响应其他命令。

所有修改命令依然写入AOF缓冲区并根据appendfsync策略同步到硬盘, 保证原有AOF机制正确性。

由于fork操作运用写时复制技术, 子进程只能共享fork操作时的内存数据。

由于父进程依然响应命令, Redis使用“AOF重写缓冲区”保存这部分新数据, 防止新AOF文件生成期间丢失这部分数据。

4)子进程按照命令合并规则写入到新的AOF文件。

每次批量写入硬盘数据量由配置
aof-rewrite-incremental-fsync控制, 默认为32MB, 防止单次刷盘数据过多造成硬盘阻塞。

5.1)新AOF文件写入完成后, 子进程发送信号给父进程

父进程收到信号后更新统计信息, 具体见info persistence下的aof_*相关统计。

5.2)父进程把AOF重写缓冲区的数据写入到新的AOF文件。

5.3)使用新AOF文件替换老文件, 完成AOF重写。

AOF修复出错文件:

AOF 的缺陷:在同样数据规模的情况下,AOF 文件要比 RDB 文件的体积大。而且,AOF 方式的恢复速度也要慢于 RDB 方式

bgrewriteaof命令: redis 会生成一个全新的 AOF 文件

AOF 文件出现了被写坏的情况:redis 并不会贸然加载这个有问题的 AOF 文件,而是报错退出。

修复出错的文件

1.备份被写坏的 AOF 文件

2.运行 redis-check-aof --fix 进行修复

3.用 diff -u 来看下两个文件的差异,确认问题点\

4.重1启 redis,加载修复后的 AOF 文件

AOF 的优点:

  • 使用AOF Redis会更具有可持久性(durable):你可以有很多不同的fsync策略:没有fsync,每秒fsync,每次请求时fsync。使用默认的每秒fsync策略,写性能也仍然很不错(fsync是由后台线程完成的,主线程继续努力地执行写请求),即便你也就仅仅只损失一秒钟的写数据。
  • AOF日志是一个追加文件,所以不需要定位,在断电时也没有损坏问题。即使由于某种原因文件末尾是一个写到一半的命令(磁盘满或者其他原因),redis-check-aof工具也可以很轻易的修复。
  • 当AOF文件变得很大时,Redis会自动在后台进行重写。重写是绝对安全的,因为Redis继续往旧的文件中追加,使用创建当前数据集所需的最小操作集合来创建一个全新的文件,一旦第二个文件创建完毕,Redis就会切换这两个文件,并开始往新文件追加。
  • AOF文件里面包含一个接一个的操作,以易于理解和解析的格式存储。你也可以轻易的导出一个AOF文件。例如,即使你不小心错误地使用FLUSHALL命令清空一切,如果此时并没有执行重写,你仍然可以保存你的数据集,你只要停止服务器,删除最后一条命令,然后重启Redis就可以。

AOF 的缺点:

  • 对同样的数据集,AOF文件通常要大于等价的RDB文件。
  • AOF可能比RDB慢,这取决于准确的fsync策略。通常fsync设置为每秒一次的话性能仍然很高,如果关闭fsync,即使在很高的负载下也和RDB一样的快。不过,即使在很大的写负载情况下,RDB还是能提供能好的最大延迟保证。
  • 在过去,我们经历了一些针对特殊命令(例如,像BRPOPLPUSH这样的阻塞命令)的罕见bug,导致在数据加载时无法恢复到保存时的样子。这些bug很罕见,我们也在测试套件中进行了测试,自动随机创造复杂的数据集,然后加载它们以检查一切是否正常,但是,这类bug几乎不可能出现在RDB持久化中。为了说得更清楚一点:Redis AOF是通过递增地更新一个已经存在的状态,像MySQL或者MongoDB一样,而RDB快照是一次又一次地从头开始创造一切,概念上更健壮。但是,1)要注意Redis每次重写AOF时都是以当前数据集中的真实数据从头开始,相对于一直追加的AOF文件(或者一次重写读取老的AOF文件而不是读内存中的数据)对bug的免疫力更强。2)我们还没有收到一份用户在真实世界中检测到崩溃的报告。

关于Redis多线程,还是单线程参考文章:

我们说它是单线程,主要是因为在以前的版本中网络 IO 和键值对读写是由一个线程来完成的。

而之所以说 Redis 是多线程,则是因为 Redis6.0 以后的版本里,网络 IO 的部分变为了多线程处理。而且除了主线程,还有 3 个辅助 BIO 线程,分别是 fsync 线程、close 线程、清理回收线程。当然不能忘记的是,想要体验多线程机制,就得通过修改配置文件开启多线程功能

AOF、RDB和复制功能对过期键的处理

生成RDB文件

在执行SAVE或者BGSAVE命令创建一个RDB文件时,Redis不会将过期键保存到RDB文件中。

载入RDB文件

如果服务器是主服务器,那么在载入RDB文件时,会对过期键进行过滤,也就是不会加载RDB中的过期键到主服务器中。 如果服务器是从服务器,那么在载入RDB文件时,不会对过期键过滤,先将RDB中的全部数据加载到从服务器中。然后再进行主从同步,删除过期键。

AOF文件写入

因为AOF采取的是追加写,所以如果过期键被删除的话,其实是向AOF文件中追加一条DEL命令,来显示的标记该key被删除了。

RDB和AOF的选择之感

  • 对数据非常敏感,建议使用默认的AOF持久化方案,AOF持久化策略使用erverysecond,每秒钟fsync一次。该策略redis任然可以保持很好的处理性能,当出现问题时,最多丢失0-1秒中的数据。
    • 注意:由于AOF文件存储体积较大,且恢复数据较慢
  • 数据呈现阶段有效性,建议使用RDB持久化方案数据可以良好的做到阶段内无丢失(该阶段是开发者或运维人工手工维护的),且恢复速度较快,阶段点数据恢复通常采用RDB方案
    • 注意:利用RDB实现紧凑的数据持久化会使Redis降得很低

综合对比

  • RDB与AOF得选择实际上是在做一种权衡,每种都有利弊
  • 如不能承受数分钟以内得数据丢失,对业务数据非常敏感,选用AOF
  • 如能承受数分钟以内数据丢失,且追求大数据集得恢复速度,选用RDB
  • 灾难恢复选用RDB
  • 双保险策略,同时开启RDB和AOF,重启后,Redis优先使用AOF来恢复数据,降低丢失数据的量

持久化应用场景

最近发表
标签列表