redis-13-AOF和RDB
AOF vs RDB 对比
redis 是一个内存型数据库,之前在《Go 语言+Redis 实战课》中签到的案例,数据是放到 redis 中,还有秒杀的案例,部分数据也是放到了 redis 中,如果这个时候,redis 故障了,redis 重新启动以后,内存中的数据肯定就全部消失了,用户是抱怨的,老板肯定也是不接受的。那 Redis 也提供了数据持久化到磁盘上的能力,就可以避免数据丢失了。
Redis 提供了两种方式保存数据数据的方式:
- RDB
- AOF
面试知识点梳理
RDB 要学什么?
什么是持久化,什么是快照?RDB 的工作原理以及优点和缺点是什么?
AOF 要学什么?
为什么要有 AOF?
如何选择 RDB 和 AOF,如何互补?
单独开启 RDB?单独开启 AOF? 还是 2 个一起开始,那 2 个都开启,数据冗余怎么考虑?
AOF 存储的是一个文件,这个文件有上限吗?
存储上限到了,怎么办?
要重写,为什么要重写?
重写的触发条件是什么?
常用的配置是什么?
文件如何写入?文件损坏了,怎么办?
redis 在运行中,开启的是 rdb,在 redis 不重启的情况下,数据不丢失的情况下,如何完成动态切换?
redis 的备份容灾,如何恢复?如何更好的恢复?
redis 如何提高性能? 从硬盘角度出发
Redis 的持久化方式
- RDB 的全称是 Redis database。顾名思义,RDB 就是将 Redis,用来存储数据的,所以通过 RDB 方式持久化就是将存在 Redis 内存中的数据写入到 RDB 文件中保存到磁盘上,从而实现持久化的。
- RDB 数据库使用操作日志记录每个操作,以防失败后通过日志恢复一致性。操作日志是按顺序追加写入的,所以不会出现无法恢复操作日志的情况。(类似 MySQL 的重做和撤销日志)。RDB 是指定时间间隔对数据进行快照存储,类似 MySQL 的 dump 备份文件。
- AOF 方式,数据库不修改旧数据,只是通过追加写入,因此数据本身就是日志,所以不会出现数据无法恢复的情况。记录每一次对服务器写操作,服务器重新启动的时候会重新执行这些命令来恢复原始的数据(类似 MySQL 的 binlog)
RDB 操作
redis.conf
1 | # 端口 |
docker-compose.yml
1 | redis: |
我们用管道的方式插入数据(之前的案例中,介绍过),我们看一下截图
在 redis 内部,运行
1 | info memory |
可以看到内存使用情况。如果没有持久化,那么当 redis 发生故障,那么内存中保存的数据就会消失,这让业务使用方是无法接受的。
在 redis.conf 中,添加如下
1 | # 5秒有1个key改动,执行快照生成 |
如果我们把 5 秒改成 900 秒,必须要等到这个时间到了,才能执行,不利于测试。
接下来重启 redis,我们运行
1 | docker-compose down |
然后我们再看 dump.rdb 文件,100 万条数据是占硬盘 33.8mb(主要也是单条数据大小决定的,也就是你的存储对象有多大决定的)。
可以停止 redis 服务,然后再次重新加载,我们观察,数据都还在,这是因为,启动的时候都会去加载 rdb 文件,把内容读取到内存。
缺点:如果我们把 5 秒,改成 900 秒,也就是 15 分钟,那么在这段时间 redis 故障,我们就会损失掉 15 分钟的数据,这个时间是很长的,对于数据使用方,也是无法接受的,可以通过 AOF 方式做补充。
Redis 默认对 RDB 保存的时间
1 | #900秒内如果超过一个key改动,触发保存快照 |
什么是 Redis 快照
刚刚说的 dump.rdb,我们就称为快照文件。
快照产生的情况,如下:
- 手动执行 bgsave。(非阻塞:当前线程仍然可以对外提供服务)
- 手动执行 save。(阻塞:由于 redis 是单线程,所以当前线程不能提供服务。)
- 根据配置文件自动执行。
- 客户端发送 shudown 命令,系统会先执行 save 命令,然后关闭服务器。(由于服务器即将关闭,所以不会接收新的请求)
- 主从架构的时候,从服务器向主服务器发送 sync 命令执行复制操作的时候,主服务器会执行 bgsave。(主节点会先做 bgsave,然后生成 rdb,然后通过 sync 命令把 rdb 发送给从节点)
RDB 原理
源码在 rdb.c 中可查看。
RDB 优点:
- 二进制,高效,备份简单,可以把 rdb 文件备份到其他 hdfs,fasthdfs 中等。数据文件在硬盘上占用也不是很大。
- fork 子进程,优化了性能
- 启动效率高。
RDB 缺点:
- 生成快照时机。生产环境一般 15 分钟或 30 分钟, 这个时间内没有生成快照,然后 redis 故障了,就会丢数据。(下面 AOF 弥补这个缺点)
- fork 子进程开销不确定性。如果数据集很大,频繁 fork,会造成性能问题。
AOF 持久化
AOF 全称 Append Only File,意思只追加文件,在每次处理完请求命令后将这个命令追加到 aof 文件末尾。默认 aof 是关闭的,开启如下:
1 | # 开启 appendonly 备份模式 |
生成了 appendonly.aof 以后
1 | *2 |
*数字 代表下面几行是命令
$数字 代表命令或值的字节长度
1 | *3 |
*3 代表下面 3 行是命令。
$3 指 set 这个命令的字节长度
$1 分别是 key 和 value 的字节长度。
看到这里,可以尝试删除 rdb 文件,然后重新启动 redis,数据还在 Redis 中。
AOF 同步策略
- 每秒同步(默认,每秒调用一次 fsync)
- 每次修改同步(会极大削弱 Redis 的性能,这种模式下每次 write 后都会调用 fsync)
- 不主动同步(操作系统决定什么时候写入磁盘)
rdb 是固定一个时间,线上环境比如 15 分钟同步一次,但是 aof 是每秒同步一次,这个效率上肯定差异巨大。
AOF 工作原理
AOF 备份与恢复
AOF 文件是一个只进行 append 操作的日志文件,写入时,出现故障或宕机,不会破坏已经写入的数据内容。即使写入一半数据出问题了,在 redis 启动之前,可以使用 redis-check-aof 工具修复即可。
AOF 对人类友好且容易读懂的。文件保存了对 redis 执行的所有操作,这些写入操作按 redis 协议的格式保存。导出 AOF 文件也很简单。如果不小心执行 FlushAll 命令,只要 AOF 文件未被重写,停止服务器,移除 AOF 文件末尾的 FlushAll 命令,重新 redis,就可以将数据都恢复到 FlushAll 之前的状态了。
重写
随着 Redis 的 AOF 文件越来越大,自动地在后台对 AOF 进行重写(Rewrite)。
默认配置
1 | auto-aof-rewrite-min-size 64mb 当文件超过64mb就重写 |
人为触发重写
1 | BgReWriteAOF |
为什么要重写
当我们对一个 Key 反复操作的时候
1 | set name 面向加薪学习 |
我们看到上面对 name 的反复操作,那么 redis 重写以后会保留最后一条,这样,更好的提高性能。
AOF 优点
- 数据不易丢失(每秒执行 1 次)
- 自动重写机制
- 易读易恢复
AOF 缺点
- AOF 文件恢复文件慢
- AOF 持久化效率低
RDB vs AOF 如何选择
同时开启
Redis 会先加载 AOF 文件恢复数据,因为 AOF 比 RDB 更完整,如果错误的操作记录写入了 AOF,会导出数据恢复失败,所以 RDB 作为备份数据,如果为了考虑性能,可以只在 Slave 上开启 RDB,因为 RDB 可能 15 分钟备份一次,为了避免 AOF Rewrite 的 I/O 操作以及阻塞,可以在 Redis 集群中不开启 AOF,靠集群的备份机制来保证可用性,在启动时选取最新的 RDB 文件,如果集群全部宕机崩溃,会丢失 15 分钟数据。
混合模式
默认开启的
1 | aof-use-rdb-preamble true |
Redis 在启动时,加载 AOF 文件,但是加载速度慢。但是,RDB 数据又不完整,所以加载 AOF。
开启后,AOF 在重写时会直接读取 RDB 的内容。
执行 bgrewriteaof 以后,运行过程:
- 子进程把内存中的数据以 RDB 的方式写入到 AOF 文件中。
- 把重写缓冲区中的增量命令以 AOF 形式写入到文件。
- 将含有 RDB 个数和 AOF 个数的 AOF 数据覆盖旧的 AOF 文件。
恢复数据
- AOF 文件开头是 RDB 格式,先加载 RDB 的内容,再加载其他的 aof 的内容。
- AOF 文件开头不是 RDB 格式,直接加载 AOF 文件。
优点:快速备份+避免大量数据丢失
缺点:RDB 是压缩模式,AOF 在读取时可读性较差
建议使用 混合模式
Redis 优化方案
独立部署,redis 的 rdb 和 aof 文件生成过程,除了对硬盘和内存造成压力,它是 cpu 密集型操作。不要和其他应用部署(MySQL 或 Kafka)到一起。MySQL 或 Kafka 也是要对磁盘造成压力。硬盘建议使用 SSD 硬盘。缓存禁用持久化。因为缓存失效后可以重新从数据库里面再拉出来,所以没必要持久化。
主从模式,从节点持久化。因为从节点都是只读节点,是不会有写入功能的。从节点数据是来自主节点的,每次复制,主节点需要一次 BgSave,磁盘要交互一次,然后生成 RDB 文件,然后再把 RDB 文件发给从节点。这就完成一次复制的过程。
优化 Fork 处理,如果从节点频繁和主节点进行数据复制,那么主节点一直执行 BgSave,也是亚历山大。主从模式可以把主节点持久化关闭,让从节点开启 RDB 的文件备份。甚至可以把 AOF 关闭,因为主从已经是高可用了,但是如果说 15 分钟内有一个节点宕机,那么其他节点的数据还存在,这个主从模式和单节点模式是不同的,因为单节点一旦挂了,什么数据就都没了。如果可以关闭 AOF,那么就是又节省了一大部分系统开销。还可以降低 AOF 重写频率。
如何学以致用,在哪些场景中应用Redis
《Go语言+Redis实战课》


添加微信 | 公众号更多内容 |
---|---|
![]() |
![]() |