AOF日志
介绍
- WAL(写前日志):先写日志后操作数据;
- AOF(后写日志):Redis先执行命令,把数据写入内存,然后才记录日志。
优势
- 避免额外的检查开销(也就是对应数据库MySQL的分析器(词法、语法));
如果先记录AOF日志的话,由于并不会先对这些命令进行语法检查,所以会依照日志的命令执行。如果日志中有错误的命令,redis在使用日志恢复数据时,就可能会出错;所以后记录日志,会保证记录的日志都是正确的。
- 不会阻塞当前的写操作;
AOF的配置项
AOF的重写机制
- 在重写时,redis根据数据库的现状创建一个新的AOF文件;
- 读取数据库中所有键值对,然后对每个键值对用一条命令记录它的写入;也即是实现了多对一的关系;
- AOF采用追加的方式,逐一记录接收到的写命令,也就是一条键值对被多条写命令反复修改,AOF会记录相应的多条命令;当AOF重写时,根据这个键值对当前的最新状态,为它生成对应的写入命令。
AOF重写不会阻塞,但是子进程拷贝数据的过程费时
- 拷贝(旧的数据):每次执行重写时,主线程fork出后台的bgrewriteaof子进程,此时fork会把主线程的内存拷贝一份到bgrewriteaof子进程,包含了数据库最新的数据。然后子进程就可以在不影响主线程的情况下,逐一把拷贝的数据写成操作,记入新的AOF日志;
- 旧的AOF日志:redis会把操作写到旧的AOF缓冲区中,这样即使宕机了,这个AOF日志操作的仍然是齐全的,可以用来恢复;
- AOF重写缓冲区:redis也会把操作写到AOF重写缓冲区中,这样AOF就不会丢失最新的操作。等待拷贝数据的所有操作记录重写完成后,重写缓冲区把这些最新的操作也写入到新的AOF中,也就完成了AOF重写。
由于AOF记录的是操作命令,而不是实际的数据。所以,AOF进行故障恢复的时候,需要逐一把操作日志都执行,如果操作日志较多,redis就会恢复的很慢,影响正常使用;
所以RDB记录的是某一时刻的数据,并不是操作;也就是在数据恢复时可以直接把RDB文件读入内存,很快完成恢复。
RDB日志(快照)
- 快照:把某一时刻的状态以文件的形式写到磁盘上。
- 为了提供所有数据的可靠性保证,提出了全量快照;也就是一次性记录所有数据,一个都不少。
RDB不会阻塞主线程
- 因为redis使用主线程fork创建出bgsave子进程,可以共享主线程的所有内存数据。bgsave子进程运行后,开始读取主线程的内存数据,并把它们写入RDB文件。这就避免了主线程的阻塞。
如何保证快照的完整性
- 当redis需要执行写操作的时候,会利用copy on write思想;会把要修改的这块数据复制一份,生成该数据的副本,bgsave子进程会把这个副本数据写入RDB文件,就会保证快照的完成性,主线程也可以正常执行读写操作。
如何设置快照执行的时间
- 增量快照:是指做了一次全量快照后,后续的快照只对修改的数据进行快照记录,这样可以避免每次全量快照的开销;但是需要我们使用额外的元数据信息去记录那些数据被修改了,这会带来额外的空间开销问题;
- 混合使用AOF日志和内存快照的方法:简单来说,内存快照以一定频率执行,在两个快照之间,使用AOF日志记录这期间的所有命令操作;这样快照不用很频繁的执行,避免了频繁fork对主线程的影响。同时AOF日志也只用记录两次快照间的操作,也就是说,不需要记录所有操作了,因此不会出现文件过大的情况,也就可以避免重写开销;等到第二次做全量快照时,就可以清空AOF日志,因为此时的修改都已经记录到快照中了,恢复的时候就不再用日志了。