Redis的持久化—RDB和AOF
Redis持久化有两种方式: RDB快照和 AOF日志
1 RDB快照
1.1 概念
RDB(Relation DataBase):将当前进程的数据生成快照(某刻时间数据的拷贝)保存到硬盘。
1.2 触发方式
- 手动触发
- 调用命令 bgsave
- 自动触发
- 根据相关配置,例如“save m n”。表示m秒内修改数据被修改n次,自动触发bgsave。
- 当从节点启动全量复制时,自动触发bgsave。
- 执行debug reload命令重新加载Redis时,也会自动触发save操作。
- 默认情况下启动shutdown命令时,若没有开启AOF持久化功能,则触发bgsave。
1.3 工作流程
- 执行bgsave命令,Redis父进程判断当前是否存在正在执行的子进程,如RDB/AOF子进程,如果存在bgsave命令直接返回。
- 父进程执行fork操作创建子进程,fork操作过程中父进程会阻塞,通过info stats命令查看latest_fork_usec选项,可以获取最近一个fork操作的耗时,单位为微秒。
- 父进程fork完成后,bgsave命令返回“Background saving started”信息并不再阻塞父进程,可以继续响应其他命令。
- 子进程创建RDB文件,根据父进程内存生成临时快照文件,完成后对原有文件进行原子替换。执行lastsave命令可以获取最后一次生成RDB的时间,对应info统计的rdb_last_save_time选项。
- 进程发送信号给父进程表示完成,父进程更新统计信息,具体见info Persistence下的rdb_*相关选项
1.4 优缺点
- 优点
- RDB文件是紧凑的二进制文件,适合于全量备份和全量复制。
- 使用RDB文件,数据恢复速度远快于AOF文件。
- 缺点
- bgsave属于重量级操作,耗时较大,无法做到实时持久化、秒级持久化。
- 不同Redis版本生成的RDB文件存在不兼容问题。
2 AOF日志
2.1 概念
AOF(append only file):以日志的方式,记录执行每次的写命令。AOF的主要作用是解决了数据持久化的实时性。
2.2 启动方式
开启AOF功能需要设置配置:appendonly yes,默认不开启。
2.3 工作流程
AOF文件的生成主要包括如下步骤:
1)命令写入(append)
2)文件同步(sync)
3)文件重写(rewrite)
2.3.1 命令写入
Redis执行的写命令追加到AOF缓冲区中。
数据首先写到缓冲区的原因:
<1> 若每一次执行写命令就同步到硬盘上,受限于硬盘的读写速度,效率不高。
<2> Redis可以提供多种缓冲区同步硬盘的策略,在性能和安全性方面做出平衡。
2.3.2 文件同步
将缓存中的数据同步到硬盘上。
Redis提供了多种AOF缓冲区同步文件策略,如表所示,由参数appendfsync控制。
策略配置参数 | 说 明 |
---|---|
always | 命令写入AOF缓冲区后,调用系统fsync操作强制同步到硬盘 |
everysec | 命令写入AOF缓冲区后,调用系统write操作,每隔1秒调用系统fsync操作强制同步到硬盘 |
no | 命令写入AOF缓冲区后,调用系统write操作,不调用系统fsync操作。同步操作交由操作系统负责,同步最长时间可达30秒 |
2.3.3 文件重写
随着文件同步的执行,AOF文件会变得越来越大,占用空间也越来越大。为此,Redis采用一些文件重写机制,压缩文件,降低文件占用的空间。
常用的压缩方式:删除超时数据记录、删除失效命令、多个等效命令合并。
Redis会调用bgrewriteaof命令开启文件重写。
文件重写的工作步骤
- T1-1
在执行AOF文件重写之前,进行如下判断:
1)如果当前进程正在执行AOF重写,请求不执行,直接返回
2)如果当前进程正在执行bgsave操作,重写命令延迟到bgsave完.成之后再执行 - T2-1
父进程调用fork创建子进程。父进程调用fork创建子进程期间会阻塞。 - T3-1、T3-1.1
在子进程创建完毕后,父进程解除阻塞,继续响应其他命令。所有修改命令依然写入AOF缓冲区。并根据appendfsync策略同步到硬盘,保证原有AOF机制正确性。 - T3-2
子进程被创建出来后,根据内存快照,按照命令合并规则写入到新的AOF文件。 - T3-3
在子进程创建完毕后,父进程解除阻塞,继续响应其他命令。由于fork的写时复制机制,子进程只知道fork执行之前父进程的内存数据,而不知fork之后父进程产生的新数据。未防止在生成新AOF文件期间丢失新产生的数据,将产生的新数据写到AOF重写缓冲区中。 - T4-1
子进程完成新AOF文件后,通知父进程。 - T5-1、T5-1.1
父进程接收到子进程的通知后,会调用一个信号处理函数,将重写缓冲区中的数追加到新AOF文件中,并替代旧AOF文件。在调用信号处理函数期间,父进程是阻塞的,防止产生新数据。
3 持久文件加载流程
参考
- 付磊. Redis开发与运维