【Redis】详细剖析RDB和AOF的过程以及区别

本文涉及的产品
Redis 开源版,标准版 2GB
推荐场景:
搭建游戏排行榜
云数据库 Tair(兼容Redis),内存型 2GB
日志服务 SLS,月写入数据量 50GB 1个月
简介: 【Redis】详细剖析RDB和AOF的过程以及区别

Redis如何保证重启后的数据恢复?

Redis是内存数据库,它将自己的数据存储在内存里面,一旦Redis服务器进程退出或者运行Redis的服务器停机,Redis中的数据就会丢失。

为了避免数据丢失,所以Redis提供了持久化机制,将存储在内存中的数据保存到磁盘中,用于在Redis服务器进程退出或者运行Redis服务器的计算机停机导致数据丢失时,快速的恢复之前Redis存储在内存中的数据。

Redis提供了2种持久化方式,分别为:

  • RDB持久化
  • AOF持久化

RDB

RDB全名为Redis Database Backup file,意为Redis数据库备份文件,也被叫做Redis数据快照。简单来说就是把内存中的所有数据记录到磁盘中。当Redis实例故障重启后,从磁盘读取快照文件,恢复数据。正是由于RDB持久化的这种特性,所以RDB持久化也叫做快照持久化。这个快照文件是一个经过压缩的二进制文件,通过该文件可以还原生成RDB文件时Redis中的数据。

Redis提供了两种命令来创建RDB文件。

  • save
  • bgsave

这两个命令有一定的区别。

save命令会直接阻塞Redis服务器进程,直到RDB文件创建完毕为止,在服务器进程阻塞期间,服务器不能处理任何请求。

bgsave命令则会通过fork创建一个子进程,然后由子进程异步的创建RDB文件,服务器进程(父进程)继续处理命令请求。

因此我们一般更多的使用的是bgsave命令。

同时在Redis的配置文件中,有一个save参数,可以用于设定Redis自动触发bgsave的条件。

默认的配置条件表示,只要满足以下3个条件中的任意1个,BGSAVE命令就会被执行:

服务器在900s(即15分钟)之内,对数据库进行了至少1次修改

服务器在300s(即5分钟)之内,对数据库进行了至少10次修改

服务器在60s(即1分钟)之内,对数据库进行了至少10000次修改

同时也可以设定Redis的备份文件的名称

这里有一个小坑,就是如果你修改完毕dbfilename之后,你再次重启你的Redis你会发现你的数据都消失了,原因是因为Redis会去配置文件中的dbfilename中查找他的RDB文件,根据这个名称去寻找这个文件,如果找到了就从中读取数据进行数据恢复。而由于你修改了这个名称,所以你再次重启的时候Redis发现没有这个文件,因此Redis会创建这个文件,并重新开始向其中记录数据,因此你原有的数据还在dump.rdb这个文件中,只不过新的数据都会记录到新的RDB文件中。

载入RDB文件的目的是为了在Redis服务器进程重新启动之后还原之前存储在Redis中的数据。

并且Redis并没有提供从RDB文件中读取数据的命令,而是每次启动Redis他都会从当前配置文件中对应的RDB文件中进行数据读取,Redis也已经在启动Redis服务的时候告诉你这一点了。

当然,Redis服务器启动时是否会载入RDB文件还取决于服务器是否启用了AOF持久化功能,具体判断逻辑为:

  • 只有在AOF持久化功能处于关闭状态时,Redis才会使用RDB文件来还原数据。
  • 如果服务器开启了AOF持久化功能,那么Redis会优先使用AOF文件来还原数据。

当然,AOF持久化功能默认是关闭的,因此默认情况下Redis都是通过RDB文件来载入数据。

AOF

AOF全称为Append Only File(追加文件)。Redis处理的每一个写命令(set,hset等)都会记录在AOF文件中,可以看作是命令日志文件。

AOF功能默认是关闭的,需要通过修改配置文件来开启。

开启 AOF 持久化后每执行一条会更改 Redis 中的数据的命令,Redis 就会将该命令写入到内存缓存 server.aof_buf 中。

AOF的命令记录的频率也是可以配置的,默认为everysec,也就是每秒。

always表示每执行一次写命令都立刻记录到AOF文件中,性能影响大

everysec表示写命令执行完毕之后先放入到AOF缓冲区中,然后每隔1s将缓冲区中的文件写入到AOF中,最多丢失1s数据

no表示写命令执行完毕后先放入AOF缓冲区,由操作系统决定何时将内容写回到磁盘中,可靠性差,可能丢失大量数据

Redis的AOF方式

Redis的AOF重写描述不准确以及一个小错误

appendfsync always    #每次有数据修改发生时都会写入AOF文件,这样会严重降低Redis的速度
appendfsync everysec  #每秒钟同步一次,显式地将多个写命令同步到硬盘
appendfsync no        #让操作系统决定何时进行同步

AOF的日志

关系型数据库(如 MySQL)通常都是执行命令之前记录日志(方便故障恢复),而 Redis AOF 持久化机制是在执行完命令之后再记录日志。

为什么是在执行完命令之后记录日志呢?

  • 避免额外的检查开销,AOF 记录日志不会对命令进行语法检查;
  • 在命令执行完之后再记录,不会阻塞当前的命令执行。

这样也带来了风险(我在前面介绍 AOF 持久化的时候也提到过)

  • 如果刚执行完命令 Redis 就宕机会导致对应的修改丢失;
  • 可能会阻塞后续其他命令的执行(AOF 记录日志是在 Redis 主线程中进行的)。

由于AOF是记录命令,因此AOF文件会比RDB文件大得多。而且AOF会记录对同一个key的多次写操作,即使其实只有最后一次写操作有意义。通过bgrewriteaof命令,可以让AOF文件执行重写功能,用最少的命令达到一样的效果。

例如对同一个name的操作,使用bgrewriteaof之后,本来记录三次的命令,直接会变成记录最后一次的命令。

set name 123
set name 234
set name 345
---bgrewriteaof----
set name 345 

而这些命令在AOF文件中记录的方式如下:

AOF重写机制

上面我已经说过,AOF的文件会比RDB文件大得多,所以,AOF提供了一种重写机制。

当 AOF 变得太大时,Redis 能够在后台自动重写 AOF 产生一个新的 AOF 文件,这个新的 AOF 文件和原有的 AOF 文件所保存的数据库状态一样,但体积更小。

AOF 重写是一个有歧义的名字,该功能是通过读取数据库中的键值对来实现的,程序无须对现有 AOF 文件进行任何读入、分析或者写入操作。

在执行 BGREWRITEAOF 命令时,Redis 服务器会维护一个 AOF 重写缓冲区,该缓冲区会在子进程创建新 AOF 文件期间,记录服务器执行的所有写命令。当子进程完成创建新 AOF 文件的工作之后,服务器会将重写缓冲区中的所有内容追加到新 AOF 文件的末尾,使得新的 AOF 文件保存的数据库状态与现有的数据库状态一致。

最后,服务器用新的 AOF 文件替换旧的 AOF 文件,以此来完成 AOF 文件重写操作。

Redis 7.0 版本之前,如果在重写期间有写入命令,AOF 可能会使用大量内存,重写期间到达的所有写入命令都会写入磁盘两次。

当然,Redis也会在触发阈值时自动去重写AOF文件,阈值也可以在redis.conf中进行配置

第一个参数表示AOF文件比上次文件增长超过百分之多少之后进行重写

第二个参数表示AOF文件体积最小多大以上才能触发重写

简而言之,Redis的AOF文件重写功能,是通过Redis服务器创建一个新的AOF文件来替代现有的AOF文件,新旧两个AOF文件所保存的数据库数据相同,但新AOF文件不会包含任何浪费空间的冗余命令,所以新AOF文件的体积通常会比旧AOF文件的体积要小很多。

而AOF文件的重写是如何实现的现在来举个例子:

因为AOF文件包含了重建数据库所需的所有写命令,所以Redis服务器只要读入并重新执行一遍AOF文件里面保存的写命令,就可以还原Redis服务器关闭之前的数据。

Redis读取AOF文件并还原数据库的详细步骤如下:

上面这个操作无非就是向一个数组添加先添加了 1 2 3,然后再出来3和2,然后又插入4 5,最终arrays中数据为1 4 5,那么我们只要lpush 5 4 1(rpush 1 4 5)即可,那么就一下子把多余的几条命令给去除了。

因为AOF文件包含了重建数据库所需的所有写命令,所以Redis服务器只要读入并重新执行一遍AOF文件里面保存的写命令,就可以还原Redis服务器关闭之前的数据。

Redis读取AOF文件并还原数据库的详细步骤如下:

  • 创建一个不带网络连接的伪客户端
    因为Redis的命令只能在客户端上下文中执行,而载入AOF文件时所使用的命令直接来源于AOF文件而不是网络连接,所以服务器使用了一个没有网络连接的伪客户端来执行AOF文件保存的写命令。
    伪客户端执行命令的效果和带网络连接的客户端执行命令的效果完全一样。
  • 从AOF文件中分析并读取出一条写命令。
  • 使用伪客户端执行被读取出的写命令。
  • 一直执行步骤2和步骤3,直到AOF文件中的所有写命令都被执行完毕。

如果Redis开启了AOF持久化功能,那么Redis服务器在启动的时候就会载入AOF文件。

因为AOF文件重写会进行大量的文件写入操作,所以执行这个操作的线程将被长时间阻塞。

因为Redis服务器使用单个线程来处理命令请求,所以如果由服务器进程直接执行这个操作,那么在重写AOF文件期间,服务器将无法处理客户端发送过来的命令请求。

为了避免上述问题,Redis将AOF文件重写功能放到子进程里执行,这样做有以下2个好处:

  • 子进程进行AOF文件重写期间,服务器进程(父进程)可以继续处理命令请求。
  • 子进程带有服务器进程的数据副本,使用子进程而不是线程,可以在避免使用锁的情况下,保证数据的安全性

AOF后台重写的步骤如下所示:

  • 服务器进程创建子进程,子进程开始AOF文件重写
  • 从创建子进程开始,服务器进程执行的所有写命令不仅要写入AOF缓冲区,还要写入AOF重写缓冲区,写入AOF缓冲区的目的是为了同步到原有的AOF文件。
    写入AOF重写缓冲区的目的是因为子进程在进行AOF文件重写期间,服务器进程还在继续处理命令请求,而新的命令可能会对现有的数据库进行修改,从而使得服务器当前的数据库数据和重写后的AOF文件所保存的数据库数据不一致。这也就是上面说的在Redis7.0之前会有两份的数据。
  • 子进程完成AOF重写工作,向父进程发送一个信号,父进程在接收到该信号后,会执行以下操作:
    1.将AOF重写缓冲区中的所有内容写入到新AOF文件中,这样就保证了新AOF文件所保存的数据库数据和服务器当前的数据库数据是一致的。
    2.对新的AOF文件进行改名,原子地覆盖现有的AOF文件,完成新旧两个AOF文件的替换。
    Redis提供了BGREWRITEAOF命令来执行以上步骤,如下图所示:

    执行完成后,打开appendonly.aof文件,发现保存arrays键的命令从六条变为了一条:

区别

持久化方式:

RDB定时对整个内存做快照,

AOF记录每一次执行的命令

数据完整性:

RDB不完整,两次备份之间会丢失,

AOF相对完整,取决于刷盘策略

文件大小:

RDB有压缩,文件体积小,

AOF记录命令,文件体积大

宕机恢复速度:

RDB很快

AOF慢

数据恢复优先级:

RDB低,因为数据完整性不如AOF

AOF,高,因为数据完整性更高

系统资源占用:

RDB高,大量CPU和内存的消耗,

AOF低,主要是磁盘IO资源,但AOF重写时会占用大量CPU和内存资源

使用场景:

RDB使用于可以容忍数分钟的数据丢失,追求赶快的启动速度的场景。

AOF使用于对数据安全性要求较高的场景。

如何选择RDB和AOF?

关于 RDB 和 AOF 的优缺点,官网上面也给了比较详细的说明。

官网说明

这里结合自己的理解简单总结一下。

RDB 比 AOF 优秀的地方 :

  • RDB 文件存储的内容是经过压缩的二进制数据, 保存着某个时间点的数据集,文件很小,适合做数据的备份,灾难恢复。
    AOF 文件存储的是每一次写命令,类似于 MySQL 的 binlog 日志,通常会必 RDB 文件大很多。当 AOF 变得太大时,Redis 能够在后台自动重写 AOF。新的 AOF 文件和原有的 AOF 文件所保存的数据库状态一样,但体积更小。不过, Redis 7.0 版本之前,如果在重写期间有写入命令,AOF 可能会使用大量内存,重写期间到达的所有写入命令都会写入磁盘两次。
  • 使用 RDB 文件恢复数据,直接解析还原数据即可,不需要一条一条地执行命令,速度非常快。
  • 而 AOF 则需要依次执行每个写命令,速度非常慢。也就是说,与 AOF 相比,恢复大数据集的时候,RDB 速度更快。

AOF 比 RDB 优秀的地方 :

  • RDB 的数据安全性不如 AOF,没有办法实时或者秒级持久化数据。
    生成 RDB 文件的过程是比较繁重的, 虽然 BGSAVE 子进程写入 RDB 文件的工作不会阻塞主线程,但会对机器的 CPU 资源和内存资源产生影响,严重的情况下甚至会直接把 Redis 服务干宕机。
    AOF 支持秒级数据丢失(取决 fsync 策略,如果是 everysec,最多丢失 1 秒的数据),仅仅是追加命令到 AOF 文件,操作轻量。
  • RDB 文件是以特定的二进制格式保存的,并且在 Redis 版本演进中有多个版本的 RDB,所以存在老版本的 Redis 服务不兼容新版本的 RDB 格式的问题。而AOF则没有这种问题,上面他记录数据的格式也很好的证明了这一点。
  • AOF 以一种易于理解和解析的格式包含所有操作的日志。你可以轻松地导出 AOF 文件进行分析,你也可以直接操作 AOF 文件来解决一些问题。比如,如果执行FLUSHALL命令意外地刷新了所有内容后,只要 AOF 文件没有被重写,删除最新命令并重启即可恢复之前的状态。

Redis 4.0 对于持久化机制做了什么优化?

由于 RDB 和 AOF 各有优势,于是,Redis 4.0 开始支持 RDB 和 AOF 的混合持久化(默认关闭,可以通过配置项 aof-use-rdb-preamble 开启)。

如果把混合持久化打开,AOF 重写的时候就直接把 RDB 的内容写到 AOF 文件开头。

这样做的好处是可以结合 RDB 和 AOF 的优点, 快速加载同时避免丢失过多的数据。当然缺点也是有的, AOF 里面的 RDB 部分是压缩格式不再是 AOF 格式,可读性较差。

官方文档的描述


相关实践学习
基于Redis实现在线游戏积分排行榜
本场景将介绍如何基于Redis数据库实现在线游戏中的游戏玩家积分排行榜功能。
云数据库 Redis 版使用教程
云数据库Redis版是兼容Redis协议标准的、提供持久化的内存数据库服务,基于高可靠双机热备架构及可无缝扩展的集群架构,满足高读写性能场景及容量需弹性变配的业务需求。 产品详情:https://www.aliyun.com/product/kvstore     ------------------------------------------------------------------------- 阿里云数据库体验:数据库上云实战 开发者云会免费提供一台带自建MySQL的源数据库 ECS 实例和一台目标数据库 RDS实例。跟着指引,您可以一步步实现将ECS自建数据库迁移到目标数据库RDS。 点击下方链接,领取免费ECS&RDS资源,30分钟完成数据库上云实战!https://developer.aliyun.com/adc/scenario/51eefbd1894e42f6bb9acacadd3f9121?spm=a2c6h.13788135.J_3257954370.9.4ba85f24utseFl
相关文章
|
1天前
|
监控 NoSQL 测试技术
【赵渝强老师】Redis的AOF数据持久化
Redis 是内存数据库,提供数据持久化功能,支持 RDB 和 AOF 两种方式。AOF 以日志形式记录每个写操作,支持定期重写以压缩文件。默认情况下,AOF 功能关闭,需在 `redis.conf` 中启用。通过 `info` 命令可监控 AOF 状态。AOF 重写功能可有效控制文件大小,避免性能下降。
|
1天前
|
存储 监控 NoSQL
【赵渝强老师】Redis的RDB数据持久化
Redis 是内存数据库,提供数据持久化功能以防止服务器进程退出导致数据丢失。Redis 支持 RDB 和 AOF 两种持久化方式,其中 RDB 是默认的持久化方式。RDB 通过在指定时间间隔内将内存中的数据快照写入磁盘,确保数据的安全性和恢复能力。RDB 持久化机制包括创建子进程、将数据写入临时文件并替换旧文件等步骤。优点包括适合大规模数据恢复和低数据完整性要求的场景,但也有数据完整性和一致性较低及备份时占用内存的缺点。
|
1月前
|
存储 缓存 NoSQL
大数据-45 Redis 持久化概念 RDB AOF机制 持久化原因和对比
大数据-45 Redis 持久化概念 RDB AOF机制 持久化原因和对比
35 2
大数据-45 Redis 持久化概念 RDB AOF机制 持久化原因和对比
|
2月前
|
存储 缓存 NoSQL
Redis中的rdb和aof
本文深入探讨了Redis的持久化机制,包括RDB和AOF两种方式。详细解释了RDB的工作原理、优势和劣势,以及AOF的实现原理、配置选项、文件重写机制和三种数据同步方式,还介绍了AOF文件修复工具redis-check-aof的使用,并通过实例展示了如何开启和配置AOF持久化方式。
Redis中的rdb和aof
|
1月前
|
存储 缓存 NoSQL
大数据-46 Redis 持久化 RDB AOF 配置参数 混合模式 具体原理 触发方式 优点与缺点
大数据-46 Redis 持久化 RDB AOF 配置参数 混合模式 具体原理 触发方式 优点与缺点
56 1
|
2月前
|
NoSQL 网络协议 Unix
1)Redis 属于单线程还是多线程?不同版本之间有什么区别?
1)Redis 属于单线程还是多线程?不同版本之间有什么区别?
59 1
|
2月前
|
存储 缓存 NoSQL
Redis 过期删除策略与内存淘汰策略的区别及常用命令解析
Redis 过期删除策略与内存淘汰策略的区别及常用命令解析
68 0
|
2月前
|
存储 NoSQL Redis
Redis的RDB快照:保障数据持久性的关键机制
Redis的RDB快照:保障数据持久性的关键机制
52 0
|
2月前
|
存储 缓存 NoSQL
深入探究Redis的AOF持久化:保障数据安全与恢复性能的关键机制
深入探究Redis的AOF持久化:保障数据安全与恢复性能的关键机制
86 0
|
2月前
|
存储 NoSQL Redis
SpringCloud基础7——Redis分布式缓存,RDB,AOF持久化+主从+哨兵+分片集群
Redis持久化、RDB和AOF方案、Redis主从集群、哨兵、分片集群、散列插槽、自动手动故障转移
SpringCloud基础7——Redis分布式缓存,RDB,AOF持久化+主从+哨兵+分片集群
下一篇
无影云桌面