RDB快照文件
由于AOF记录的是操作命令,而不是实际的数据。所以,用AOF方法进行故障恢复的时候,需要逐一把操作日志都执行一遍。如果操作日志很多,那Redis恢复的就很慢,影响到正常使用。那有没有即保证可靠性,还能在宕机时实现快速的恢复办法呢?那就是内存快照。对于Redis来说,它把某一时刻的状态以文件的形式写到磁盘上。这样一来,即使宕机,快照文件也不会丢失,数据的可靠性得到了保证。这个快照文件就叫RDB(Redis DataBase)文件。和AOF相比,RDB记录的是某一时刻的数据,并不是操作,所以,在做数据恢复时,直接把RDB文件加载到内存里,很快的完成恢复。
Redis提供了两个命令来生成RDB文件,分别是save和bgsave。
save:在主线程中执行,会导致阻塞。
bgsave:创建一个子进程,专门用于写入RDB文件,避免主线程的阻塞。这也是redis生成RDB文件的默认配置。
所以,我们可以采用bgsave来执行全量快照,既保证了可靠性,又避免了Redis的性能影响。接下了,我们来思考这么一个问题,就是Redis在做全量快照时,Redis中的数据可以被修改吗?Redis还支持写操作吗?为了快照而暂停写操作,Redis肯定是不能接受的。所以Redis借助了操作系统提供的写时复制技术(Copy-On-Write,COW)。简单来说,bgsave子进程是由主线程fork生成的,可以共享主线程的所有内存数据。bgsave运行之后,开始读取主线程中的内存数据,并把他们写入RDB文件。此时,如果主线程对这些数据进行读操作,则主线程和bgsave子进程相互不影响。但是,如果主线程执行写操作或者修改操作,也就是修改内存中的一块数据,那么这块数据会复制一份,生成副本。然后主线程在副本上进行修改。同时,bgsave子进程继续把原来的数据写入RDB文件。这样既保证了快照的完整性,也避免了对正常业务的影响。
接下来我们来看下一个问题,就是多久做一次快照,如果快照隔的时间太久,丢的数据就越多,间隔时间太短,丢失的数据越少,但是频繁的执行全量快照会给磁盘带来很大的压力。由于fork创建子进程bgsave这个过程是需要阻塞主线程的,主线程的内存越大,fork时间越长。所以频繁的fork出bgsave子进程,也就会频繁阻塞主线程。那有什么好的办法既能利用RDB的快速恢复,又能以较小的开销做到尽量少丢数据呢。Redis4.0提出了一个混合使用AOF日志和RDB的方法。简单来说,内存快照以一定的频率执行,两次快照之间使用AOF记录操作命令。
最后总结一下,关于AOF和RDB的选择问题,给大家提供3点建议。
数据不能丢失时,内存快照和 AOF 的混合使用是一个很好的选择。
如果允许分钟级别的数据丢失,可以只使用 RDB。
如果只用 AOF,优先使用 everysec 的配置选项,因为它在可靠性和性能之间取了一个平衡。
更多硬核知识,请关注公众号”老韩随笔"。