redis 持久化学习笔记
本文摘抄自这里
RDB 持久化
RDB 就是Redis DataBase 的缩写,中文名为快照/内存快照,RDB持久化是把当前进程数据生成快照保存到磁盘上的过程,由于是某一时刻的快照,那么快照中的值要早于或者等于等于内存中的值
触发方式
手动触发
- save 命令:阻塞当前Redis 服务器,直到RDB过程完成为止,对于内存比较大的实例会造成长时间阻塞
- gbsave命令: Redis 进程执行fork 操作创建子进程,RDB持久化过程由子进程负责,完成后自动结束。阻塞只发生fork阶段
bgsave 过程如下:

自动触发
- redis.conf 中配置save m n ,即在m秒内有n次修改时,自动触发bgsave 生成rdb文件;
- 主从复制,从节点要从主节点全量复制时也会触发bgsave操作,生成当时的快照发送到从节点
- 执行debug reload 命令重新加载redis时也会触发bgsave操作
- 默认情况下执行shutdown命令时,如果没有开启AOF持久化,那么也会触发bgsave操作
RDB 深入
RDB执行过程中,客户端新写入的数据,如何保持数据一致性
- RDB 核心思路是Copy-On-Write,来保证进行快照操作的这段时间,需要压缩写入磁盘上的数据在内存中不会发生变化。在正常的快照操作中,一方面Redis住进程会fork一个新的快照进程专门来做这个事情,这样Redis服务不会停止对客户端包括写请求在内的任何相应。另一方面这段时间发生的数据变化会以副本的方式放在另一个新的内存区域,待快照操作结束后才会同步到原来的内存区域
进行快照操作这段时间,如果服务器发生崩溃怎么办?
- 没有将数据全部写入磁盘前,这次快照操作不算成功。如果服务器出现崩溃的情况,将以上一次完成的RDB快照文件作为恢复内存数据的参考。也就是说,在快照操作过程中,不能影响上一次的备份数据。Redis服务会在次盘上创建一个临时文件进行数据操作,待操作成功后才会用这个临时文件替换掉上一次的备份。
可以每秒做一次快照吗?
- 频繁的RDB备份,一方面会给次盘带来很大的压力,另一方面fork操作会阻塞主进程,频繁的RDB就会频繁的阻塞主进程
RDB优缺点
优点
- RDB文件是某个时间节点的快照,默认使用LZF算法进行压缩,压缩后的文件体积远小于内存大小,使用于备份、全量复制等场景
- Redis 加载RDB文件恢复数据远远快于AOF方式;
缺点 - RDB方式实时性不够,无法做到秒级的持久化
- 每次调用bgsave 都需要fork子进程,fork子进程属于重量级操作,频繁执行成本较高;
- RDB文件是二进制,没有可读性,AOF文件在了解其结构的情况下可以手动修改或者补全;
- 版本兼容RDB文件问题
AOF持久化
Redis 是“写后”日志,Redis 先执行命令,把数据写入内存,然后才记录日志。日志里记录的是Redis 收到的每一条命令,这些命令是以文本形式保存。
“写后”日志的好处:
- 避免额外的检查开销:Redis在向AOF里面记录日志的时候,并不会先去对这些命令进行语法检查。所以,如果先记录日志再执行命令的话,日志中就可能记录了错误的命令。
- 不会阻塞当前的写操作
但这种方式存在风险: - 如果命令执行完成,写日志之前宕机了,会丢失数据
- 如果主进程写磁盘压力大,导致写盘慢,阻塞后续操作
AOF的实现
AOF日志记录了Redis 的每个写命令,步骤分为:命令追加(append)、文件写入(write)和文件同步(sync).
- 命令追加 当AOF持久化功能开启,服务器在执行完一个写命令后,会以协议格式将被执行的写命令追加到服务器的aof_buf缓冲区。
- 文件写入和同步 关于何时将aof_buf缓冲区的内容写入AOF文件中,Redis 提供了三种写回策略:
![]()
Always, 同步写回:每个写命令执行完毕后,立马同步地将日志写回磁盘;
Everysec, 每秒写回:每个写命令执行完,只是先把日志写到AOF文件的内存缓冲区,每隔一秒把缓冲的内容写入磁盘;
No, 操作系统控制的写回:每个写命令执行完,只是先把日志写到AOF文件的内存缓冲区,由操作系统决定何时将缓冲区内容写回磁盘
AOF重写
AOF会记录每个写命令到AOF文件,随着时间越来越长,AOF文件会变得越来越大。如果不加以控制,会对Redis服务器,甚至对操作系统造成影响,而且AOF文件越来越大,数据恢复也越慢。为了解决AOF文件体积膨胀的问题,Redis 提供了AOF文件重写机制来对AOF文件进行瘦身。
图例解释AOF重写

AOF重写会阻塞吗
AOF重写过程中由后台进程bgrewriteaof来完成。主线程fork出后台的bgrewriteaof子进程,for会把主线程的内存拷贝一份给bgrewriteaof子进程,这里面就包含数据库的最新数据。然后bgrewriteaof子进程就可以在不影响主线程的情况下,逐一把拷贝的数据写成操作,记入重写日志。
所以AOF在重写时,在fork进程时是会阻塞主线程的。
AOF何时会重写
有两个配置控制AOF重写的触发:
auto-aof-rewrite-min-size:这表示运行AOF重写时文件的最小大小,默认为64MB。
auto-aof-rewrite-percentage: 这个值的计算方式是,当前AOF文件大小和上一次重写后AOF文件大小的差值,再除以上一次重写后AOF文件大小。
重写日志时,有新数据怎么处理?
如果有新的数据写入,主线程就会将命令记录到两个AOF日志内存缓冲区中,如果AOF写回策略配置的是always,则直接将命令写回旧的日志文件,并且保存一份命令至AOF重写缓冲区,这些操作对新的日志文件是不存在的影响。
bgrewriteaof子进程完成日志文件的重写操作后,会提示主线程已经完成重写操作,主线程会将AOF重写缓冲区中的命令追加到新的日志文件的后面。这个时候在高并发的情况下,AOF重写缓冲区积累可能会很大,这样就会造成阻塞,Redis后来通过Linux管道技术让AOF重写期间就能同时进行回放,这样AOF重写结束后只需回放少量剩余的数据即可。
最后通过修改文件名的方式,保证文件切换的原子性。
在AOF重写日志期间发生宕机的话,因为日志文件还没切换,所以恢复数据时,用的还是旧的日志文件

浙公网安备 33010602011771号