【Redis】Redis持久化之AOF详解(Redis专栏启
一、什么是Redis AOF
Redis提供了两种持久性机制:一种是RDB也称为快照模式,一种是AOF日志也称为追加模式。
AOF是一个日志文件,Redis的每个命令都将以AOF格式写入AOF文件,AOF日志仅记录修改内存的指令,AOF日志记录不同于MySQL先写入日志然后再执行操作(两阶段提交),AOF是执行成功的命令,然后记录命令在日志文件中,当需要恢复时,直接导入AOF文件以执行其中的记录,并且记录是实时的,AOF日志存储Redis服务器的顺序指令序列。
二、如何开启AOF持久化
AOF 机制默认处于未开启状态,通过在配置文件中将appendonly参数配置为yes来启用AOF持久性。
#修改配置文件:vim /etc/redis/redis.confappendonly yes # 把 no 改为 yes #确定存储文件名是否正确appendfilename "appendonly.aof" #重启服务:sudo /etc/init.d/redis-server restart
三、AOF的原理
每当修改Redis的命令时,服务器都会将该命令写入appendonly.aof 文件,该文件存储服务器执行的所有修改(成功的)命令。因此,只要服务器执行aof文件,可以达到恢复数据的目的,这个过程也称为命令重演。
1、AOF持久化实现
AOF持久性的实现可以分为:命令追加( append ,当AOF持久性功能打开时,Redis将在执行写入命令后,以协议格式(即RESP,Redis客户端和服务器之间的通信协议)将执行的写入命令附加到Redis服务器维护的AOF缓冲区的末尾。)、文件写入( write,Redis将调用flushAppendOnlyFile函数,以确定是否需要在每个事件周期结束之前将AOF缓存中的内容写入并同步到AOF文件)、文件同步( sync )、文件重写(rewrite)和重启加载(load)这几步。如下图所示
Redis将在执行写操作命令会将命令追加到 server.aof_buf 缓冲区,所有写入命令都将添加到AOF缓存中,然后通过 write() 系统调用,将aof_buf 缓冲区中数据写入aof文件。此时,数据还没有写入硬盘,而是复制到内核缓冲区的页面缓存 page cache,等待内核将数据写入硬盘,内核缓冲区中的数据何时写入硬盘由内核决定。
AOF缓存将根据相应的策略与硬盘同步,AOF日志将越来越大就需要定期重写以实现压缩,当Redis重新启动时,可以加载AOF文件进行数据恢复。
2、AOF数据恢复
AOF文件包含重建Redis数据所需的所有写入命令,因此只要重新读入并执行保存在AOF文件中的写入命令,Redis就可以恢复Redis关闭前的状态。伪客户端是指 Redis命令只能在客户端的上下文中执行,用于加载AOF文件的命令直接来自AOF文件,而不是网络连接。因此,服务器使用没有网络连接的伪客户端来执行保存在AOF文件中的命令。伪客户端执行命令的效果与具有网络连接的客户端的效果完全相同。
3、AOF三种写回硬盘策略
Redis 3 种写回硬盘的策略,说的是在 redis.conf 配置文件中的 appendfsync 配置项可以有以下 3 种参数可填。
Redis将在结束每个事件之前调用 flushAppendOnlyFile() 函数,以确定是否需要将AOF缓存中的内容写入并同步到AOF文件。flushAppendOnlyFile() 函数的行为由redis.conf 配置中appendfsync选项的值决定,有三个可选值:always、everysec和no。
Always(同步写回):在执行每个写操作命令后,AOF日志数据将同步写回硬盘;
Everysec(每秒写回):在执行每个写操作命令后,将命令写入AOF文件的内核缓冲区,然后每秒将缓冲区的内容写回硬盘;
No(操作系统控制的回写)意味着回写硬盘的时间不受Redis控制,而是转移到由操作系统所控制的回写入时间。也就是说,在执行每个写操作命令之后,该命令首先被写入AOF文件的内核缓冲区,然后操作系统决定何时将缓冲区内容写回硬盘。
这三种方法都有缺点:Always(同步写回),如果每次执行后命令都同步到瓷盘中,这会影响主线程的性能;Everysec(每秒回写)使用每秒回写一次的频率,以避免同步回写的性能开销。虽然它减少了对系统性能的影响,但如果发生中断,在最后一秒没有中断的命令操作仍将丢失;No(操作系统控制写回)。保存到磁盘的操作由操作系统控制。只要AOF中没有写回命令,一旦服务器停机,数据就会丢失;
写回策略 | 写回时间 | 优点 | 缺点 |
Always | 同步写回 | 可靠性高,最大程度保证安全性 | 性能开销大 |
Everysec | 每秒写回 | 性能适中 | 宕机时有1秒的数据丢失 |
No | 操作系统控制的回写 | 性能好 | 宕机存在丢失数据较大 |
4、AOF重写机制
重写机制,就是重写旧日志中的多个命令变为新日志中的一个命令。
假设对列表进行n次修改后,一条数据处于“***”状态。只有LPUSH u:list“**” 命令可以恢复数据,这为n-1个命令节省了空间,AOF重写后,日志文件将收缩,但将整个数据库的最新数据的操作日志写回磁盘仍然是一个耗时的过程。
重写不会阻塞主线程,重写过程由后台线程bgrewriteaof完成,这也是为了避免阻塞主线程,从而导致数据库性能下降。
Redis设置了一个AOF重写缓冲区,该缓冲区将在服务器创建子进程后使用,当Redis执行写命令时,它将同时向AOF缓冲区和AOF重写缓冲区发送写命令。当子进程完成AOF重写时,它将向父进程发送信号。在接收到信号后,父进程将调用信号处理函数将AOF重写缓冲区中的所有内容写入新的AOF文件,以确保新AOF文件保存的数据库状态与服务器的当前状态一致,并重命名新的AOF文件,自动覆盖现有AOF文件并完成新旧文件的替换继续处理客户端请求命令。
5、为什么Redis AOF要先执行命令后写日志?
Redis在向AOF里面记录日志的时候,不会首先检查这些命令。因此,如果它先记日志然后执行命令,则可能会在日志中记录错误的命令,Redis在使用日志恢复数据时可能会出错,如果Redis也先写日志,然后再操作,那么AOF日志中会有许多无效/错误的命令记录。
与MySQL和其他数据库的事务机制相比,Redis事务可以称为弱事务。如果事务中发生错误,将继续执行。如果事务失败,Redis不会回滚,对于此类事务,将有许多命令无法成功修改数据,如果先写日志,也会有很多无效的命令。
这两种风险都与AOF写回磁盘的时间有关。如果控制线写命令,再写AOF日志就可以解决这两个问题。
四、AOF和RDB对比
全量备份,一次保存整个数据库。 | 增量备份,一次只保存一个修改数据库的命令。 |
每次执行持久化操作的间隔时间较长。 | 保存的间隔默认为一秒钟(Everysec) |
数据保存为二进制格式,其还原速度快。 | 使用文本格式还原数据,所以数据还原速度一般。 |
执行 SAVE 命令时会阻塞服务器,但手动或者自动触发的 BGSAVE 不会阻塞服务器 | AOF持久化无论何时都不会阻塞服务器。 |
1、进行数据恢复时,既有 dump.rdb文件,又有 appendonly.aof 文件,应该首先通过appendonly.aof 恢复数据,这可以最大程度地确保数据安全。
2、只需要数据备份,不太关心一小部分数据的丢失,那么可以使用RDB模式,RDB文件也易于迁移并放入多个实例中进行数据恢复
五、Redis4.0的混合持久化模式
Redis 4.0的新特性是混合持久化模式,混合持久化模式同时使用RDB快照和AOF日志的混合持久模式,将RDB文件内容和增量AOF文件内容存储在同一个文件(相同的AOF格式文件)中,可以通过配置参数 aof-use-rdb-preamble 来启用混合持久性模式,config get aof-use-rdb-preamble命令进行查看。
由于RDB快照数据和AOF日志数据存储在同一个文件中,因此AOF格式文件不再只存储全部AOF日志,而是第一部分存储RDB快照,第二部分存储从RDB快照持久化开始到持久化结束的增量AOF日志。因此,RDB数据通常占大多数,AOF日志只是增量日志的一小部分
在混合持久策略下,当重新启动下一个Redis实例时,首先加载RDB快照的内容,然后重放增量AOF日志。这可以取代以前的RDB完全导入或AOF完全重放。