日志是任何系统或者软件中必不可少的,同样在Redis中AOF日志也是Redis用来持久化的重要手段之一。
AOF日志的实现
我们比较熟悉的MySQL中redo log用到了WAL(Write-Ahead Logging)技术,它是先写日志,再写磁盘,相比较而言,在Redis中与其相反,是后写日志。
在Redis中AOF日志的实现都是先写命令,再记录日志,为什么要先执行命令再记录日志呢,而不是像传统的数据库日志。
后写日志的方式,就是先让系统执行命令,只有命令执行成功,才会被记录到日志中,否则直接向客户端报错,这样也就避免了日志中记录错误的命令。另外在命令执行后记录日志,不会阻塞当前的写操作。
存在的风险
AOF也会存在一定的风险,那就是没来及记日志系统就宕机了,就存在命令和数据丢失的风险,如果使用Redis做缓存还可以从数据库进行数据恢复,但是如果直接用作数据库的话,就无法通过日志进行恢复了,其次后写日志虽然对当前命令不会阻塞,但是对下一个操作可能带来阻塞(AOF是在主线程中执行,如果日志文件写入磁盘,磁盘写入很慢,就会影响后续操作)。
对于这个问题,AOF提供了三种回写策略:
- Always,同步写回,每个命令执行完,立马同步将日志写回磁盘
- Everysec,每秒写回,每个命令执行完,先把日志写到AOF文件的内存缓冲区,每隔一秒写入磁盘
- NO,操作系统控制:每个命令执行完,先把日志写到AOF文件的内存缓冲区,有操作系统控制将缓冲区写到磁盘的时间
这三种策略其实没有好坏,只是看需求来使用。
配置项 | 写回时间 | 优点 | 缺点 |
---|---|---|---|
Always | 同步写回 | 可靠性高,数据基本上不丢失 | 每个写命令要落盘,性能影响大 |
Everysec | 每秒写回 | 性能适中 | 宕机丢失一秒内的数据 |
No | 操作系统控制 | 性能好 | 宕机时丢失数据较多 |
AOF随着日志的越写越多,也会存在一些性能问题,比如:文件系统本身对文件大小的限制;文件太大,在往里面追加命令记录时,效率会变低;如果发生宕机,AOF记录被执行来恢复数据时,文件太大那么时间会很漫长;此时就用到了AOF的重写机制。
AOF的重写机制就是在Redis中创建一个新的AOF日志文件。我们知道AOF是以追加的形式记录命令,一个键值可能被多次修改,这也就意味着AOF中存在多条修改日志信息。而重写机制,只会根据键值的当前最新状态,生成一条写入命令,这样重写日志中只有一条命令。
如图所示,原AOF记录了6次修改记录,也就存在6条记录,AOF重写之后就存在一条记录。
AOF的重写机制是由后台线程bgrewriteaof完成的,和AOF的主线程不一样,这也是为了避免阻塞主线程导致性能下降。Redis在fork一个子进程时,会将内存也拷贝一份给bfrewriteaof子进程,更准确地来说是子进程只是拷贝了父进程的页表,也就是一种虚拟映射关系,并非实际的拷贝一份内存数据。