Redis持久化——AOF日志

上一篇文章Redis持久化——内存快照(RDB)我们总结到使用Redis内存快照进行持久化,在t 时刻做了一次快照,然后又在 t+n 时刻做了一次快照,此时如果宕机,则会丢失在此期间内修改的数据。但又不能频繁的进行内存快照,那么有什么办法能够尽可能的减少这种数据丢失呢?Redis提供了另一种持久化的方式——AOF日志(Append Only File)。

什么是AOF日志持久化 执行后写日志

与内存快照保存当前内存中的数据所不同,AOF持久化是通过保存Redis服务器所执行的写命令来记录数据库状态的。即每执行一个命令,就会把该命令写到日志文件里。

需要注意的是写日志的操作在Redis执行命令将数据写入内存之后,如下图所示:

AOF-1

这样做的好处就是不会阻塞当前操作,也可以避免额外的检查开销,如果是在命令执行前进行写日志的操作,一旦命令语法是错误的,不进行检查的话就会导致写入到日志文件中的命令是错误的,在使用日志文件恢复数据的时候就会出错。而在命令执行后在进行日志的写入则不会有这个问题。

但是也存在两个问题,

AOF 虽然避免了对当前命令的阻塞,但却可能会给下一个操作带来阻塞风险。因为,AOF 日志是在主进程中执行的,如果在把日志文件写入磁盘时,磁盘写压力大,就会导致写盘很慢,进而导致后续的操作也无法执行了

如果刚执行完一个命令,还没有来得及记日志就宕机了,那么这个命令和相应的数据就有丢失的风险。如果此时 Redis 是用作缓存,还可以从后端数据库重新读入数据进行恢复,但是,如果 Redis 是直接用作数据库的话,此时,因为命令没有记入日志,所以就无法用日志进行恢复了。

AOF 缓冲区

针对上面两个问题,Redis提供了缓冲区的方式进行AOF日志的记录,以达到尽可能的避免阻塞和数据丢失的问题。

即Redis在执行完命令进行持久化的时候,并非直接写入磁盘日志文件,而是先写入AOF缓冲区内,之后再通过某种策略写到磁盘。

AOF-2

使用缓存区的方式进行AOF日志的记录,上面提到的两个问题其实就和日志从缓冲区写入磁盘的时机有关系。

三种回写策略

Redis AOF 机制提供了三种回写磁盘的策略。

Always(同步写回): 命令写入 AOF缓冲区后调用系统 fsync操作同步到AOF文件, fsync完成后线程返回

Everysec(每秒写回): 命令写人 AOF缓冲区后调用系统 write操作, write完成后线程返回。 fsync同步文件操作由专门线程每秒调用一次

No(操作系统自动写回): 命令写入 AOF缓冲区后调用系统 write操作,不对AOF文件做 fsync同步,同步硬盘操作由操作系统负责,通常同步周期最长30秒

但其实可以看出这三种回写策略都并不能完美的解决问题,

配置为 always时,每次写入都要同步AOF文件,硬盘的写入速度无法与内存相提并论,显然与 Redis髙性能特性背道而驰

配置为no,由于操作系统每次同步AOF文件的周期不可控,而且会加大每次同步硬盘的数据量,虽然提升了性能,但数据安全性无法保证。

配置为 everysec,是建议的同步策略,也是默认配置,虽然能做到兼顾性能和数据安全性。但极端情况下一会造成1秒内的数据丢失。

在真正使用中,我们可以根据具体对性能和数据完整性的要求,分析这三种回写策略,选择适合的策略来进行持久化。

回写策略 优点 缺点
Always(同步写回)   可靠性高、数据基本不丢失   性能较差  
Everysec(每秒写回)   性能适中   宕机时丢失1秒内的数据  
No(操作系统自动写回)   性能好   宕机时丢失数据较多  
AOF重写 日志文件越来越大怎么办

选择了合适的回写策略,AOF这种持久化的方式还有其它问题吗?

因为AOF持久化是通过保存被执行的写命令来记录数据库状态的,所以随着时间的流逝,AOF文件中的内容会越来越多,文件的体积也会越来越大,过大的AOF文件不仅追加命令会变慢,而且可能对Redis服务器、甚至整个宿主计算机造成影响,并且AOF文件的体积越大,使用AOF文件来进行数据还原所需的时间就越多。

这个时候就要用到AOF重写机制了

redis> set testKey testValue OK redis> set testKey testValue1 OK redis> del testKey OK redis> set testKey hello OK redis> set testKey world OK

内容版权声明:除非注明,否则皆为本站原创文章。

转载注明出处:https://www.heiqu.com/wsszxp.html