Redis的持久化RDB和AOF
大约 5 分钟
1. 简介
Redis是基于内存的数据库, 一旦发生发生宕机所有的数据就都会丢失,此时如果从数据库再次同步数据会影响数据库的性能。因此Redis提供了自身的持久化方法
目前有四种持久化方案: RDB、AOF、虚拟内存(VM)和DISKSTORE,但后两者并不被建议使用, 所以主流的方案只剩下了RDB和AOF
2. RDB(Redis DataBase)
RDB持久化将当前进程的数据保存到磁盘上,快照的值可能早于当前的值, 可以手动或自动触发
2.1 触发方式
2.1.1 手动触发
- save: 阻塞当前Redis服务器,直到RDB过程完成为止,对于内存 比较大的实例会造成长时间阻塞,线上环境不建议使用
- bgsave命令: Redis进程执行fork操作创建子进程,RDB持久化过程由子 进程负责,完成后自动结束。阻塞只发生在fork阶段,一般时间很短
bgsave流程如下:
- redis客户端执行bgsave命令或者自动触发bgsave命令
- 主进程判断当前是否已经存在正在执行的子进程,如果存在,那么主进程直接返回
- 如果不存在正在执行的子进程,那么就fork一个新的子进程进行持久化数据,fork过程是阻塞的,fork操作完成后主进程即可执行其他操作
- 子进程先将数据写入到临时的rdb文件中,待快照数据写入完成后再原子替换旧的rdb文件
- 同时发送信号给主进程,通知主进程rdb持久化完成,主进程更新相关的统计信息(info Persitence下的rdb_*相关选项)
注意
bgsave不阻塞主进程,也不能频繁执行,这样会导致频繁的全量写入磁盘和频繁的fork子进程,影响性能。
这个时候就需要增量同步了
2.1.2 自动触发
自动触发的四种条件:
- redis.conf中配置
save m n
,即在m秒内有n次修改时,自动触发bgsave生成rdb文件 - 主从复制时,从节点要从主节点进行全量复制时也会触发bgsave操作,生成当时的快照发送到从节点
- 执行debug reload命令重新加载redis时也会触发bgsave操作
- 默认情况下执行shutdown命令时,如果没有开启aof持久化,那么也会触发bgsave操作
2.2 RDB的优缺点
- 优点
- RDB使用LZF压缩算法, 压缩后的提及远小于原内存大小
- RDB加载恢复的速度远快于AOF方法
- 缺点
- 实时性不强,不能频繁同步
2.3 深入理解
1. RDB如何保证同步期间的数据一致性
在RDB同步的时候(bgsave)会fork一个进程数据,但是在存储的过程中,主进程的数据仍有可能被修改,如果发生修改则将未修改的数据单独复制一份,RDB继续读取这个副本即可
2. 快照期间Redis崩溃怎么办
当次快照不生效,使用最后一次成功的快照恢复Redis数据
3. AOF(Append Only File)
不同于MySQL等日志,Redis考虑到高性能的需求,其AOF采用的是写后日志,即先写入数据再记录日志,这样做的好处有:
- 避免语法检查: 因为写成功了,所以不需要再次检查
- 不阻塞写操作: 先写后记
但也存在着缺点:
- 在写后和记前,如果发生了宕机,则会发生数据丢失
- 主线程写入磁盘,导致写盘慢、阻塞后续操作
- 触发AOF重写时,需要fork主进程,导致短暂阻塞
2.1 实现方式
- 命令追加:命令追加到服务器的aof_buf缓冲区
- 文件写入和同步: AOF提供三种策略来决定何时将缓存区的命令写入磁盘
- Always: 每次命令执行完就写入
- Everysec: 每秒写入一次
- No: 操作系统决定何时写入
2.2 AOF重写
1. AOF文件重写
AOF记录着每次的命令,但有些命令是冗余的, 比如连续两条set key a
和set key b
显然可以合并成set key b
,Redis通过文件重写机制来对AOF文件进行精简
2. AOF重写时机
提供了两种重写的时机:
auto-aof-rewrite-min-size
: 表示运行AOF重写时文件的最小大小,默认为64MBauto-aof-rewrite-percentage
: (当前AOF大小 - 上次重写后AOF大小)/上次重写后AOF大小, 达到这个值就重写
3. 重写期间Redis崩溃怎么办
当次重写失效,依旧使用旧日志
4. 重写过程
- 主线程fork出子进程重写AOF日志
- 此时有新的数据写入,主线程将命令记录到两个AOF日志缓冲区(此时如果时always写回则直接写入到日志文件,否则等重写完成后追加到新的日志文件中)
- 子线程重写日志完成后,主线程追加AOF日志缓冲
- 替换原日志文件
3. 数据恢复
数据恢复只需重启Redis即可:
- Redis重启后首先检查是否存在AOF,Redis会优先加载AOF
- 如果AOF不存在则会检查是否存在RDB,并加载
- 如果RDB不存在则正常启动
4. RDB+AOF混合方式
Redis 4.0中提出了一种混合方法
- RDB以一定的频率执行,成功后清空AOF日志
- 在两次RDB之间用AOF记录期间操作
这样就可以即享受RDB的速度优势,又可以享受AOF的实时性优势了