redis灵魂拷问:AOF文件可以保存RDB格式吗

it2025-08-21  4

目录

混合日志

RDB默认配置

RDB失败怎么办

 总结


AOF文件保存的是一条一条的写命令,它的优点很明显,保存了所有的写命令,可靠性高。但是缺点也很明显,在写操作频繁的redis使用场景,AOF文件会非常大,使用AOF进行故障恢复或者全量同步,需要依次执行每一条命令,效率很低。

RDB文件是一个内存快照,记录了redis某一时刻的数据快照,而不是一条条命令。而且RDB是二进制格式保存的,无论是写磁盘还是网络传输,效率都很高,所以RDB更适合做故障恢复和全量数据同步。但是RDB的缺点也很明显,它保存的只是某一时刻的数据快照,如果redis发生故障,上一次快照和故障之间的写命令就丢失了?

如下图,执行一个快照后,key2修改了,还没来得及下一次快照,redis发生故障,key2的这一次写操作就丢失了。

混合日志

redis4.0提出了混合使用AOF和RDB快照,在AOF文件中也可以记录RDB格式的日志。这个配置参数在redis.conf文件中,最新版本中默认是开启的。

# When rewriting the AOF file, Redis is able to use an RDB preamble in the # AOF file for faster rewrites and recoveries. When this option is turned # on the rewritten AOF file is composed of two different stanzas: # # [RDB file][AOF tail] # # When loading Redis recognizes that the AOF file starts with the "REDIS" # string and loads the prefixed RDB file, and continues loading the AOF # tail. aof-use-rdb-preamble yes

 我们看一下这个配置项上面的说明。上篇文章《redis灵魂拷问:聊一聊AOF日志重写》讲到了AOF重写。​AOF重写的时候会redis把AOF文件内容清空,然后记录一份RDB快照,这份数据以"REDIS"开头。记录RDB内容后,AOF文件会接着记录下次快照之前的写命令。这样就不用担心redis故障引起的数据丢失了。

在数据恢复时,redis首先会识别以"REDIS"开头的RDB日志并加载,然后再执行后面的写命令。

RDB默认配置

redis.conf中默认有下面的配置:

################################ SNAPSHOTTING ################################ # # Save the DB on disk: # # save <seconds> <changes> # # Will save the DB if both the given number of seconds and the given # number of write operations against the DB occurred. # # In the example below the behaviour will be to save: # after 900 sec (15 min) if at least 1 key changed # after 300 sec (5 min) if at least 10 keys changed # after 60 sec if at least 10000 keys changed # # Note: you can disable saving completely by commenting out all "save" lines. # # It is also possible to remove all the previously configured save # points by adding a save directive with a single empty string argument # like in the following example: # # save "" save 900 1 save 300 10 save 60 10000

 上面的注解讲到,一个时间段内的请求数量决定了要不要写RDB日志。跟写AOF日志类似,redis主线程会fork一个bgsave子进程,fork完成之前主线程是阻塞的,而且fork之后bgsave子进程会跟主线程共用内存空间,如果这时有写请求到来,主线程只能通过CopyOnWrite来记录写数据。

RDB失败怎么办

默认情况下,如果bgsave子进程写RDB文件时出错了,redis会决绝新的写请求。比如redis因为内存原因执行快照失败,这时就不能接受新的写请求了,如果还想继续执行写命令,就把下面的参数设置为no,但这个可能不能解决根本问题,比如内存紧张导致的快照失败。

# By default Redis will stop accepting writes if RDB snapshots are enabled # (at least one save point) and the latest background save failed. # This will make the user aware (in a hard way) that data is not persisting # on disk properly, otherwise chances are that no one will notice and some # disaster will happen. # # If the background saving process will start working again Redis will # automatically allow writes again. # # However if you have setup your proper monitoring of the Redis server # and persistence, you may want to disable this feature so that Redis will # continue to work as usual even if there are problems with disk, # permissions, and so forth. stop-writes-on-bgsave-error yes

 总结

1.redis写RDB跟写AOF日志类似,都需要fork子进程,fork过程都要阻塞主线程,如果这时写命令到来,主线程都需要COW的方式进行写操作。 2.AOF和RDB日志混合使用大大减少了AOF文件的大小,同时提高了全量数据同步或和故障恢复的效率。 3.RDB快照执行出错,redis默认会停止接收写请求,这个可以配置,但是要确定快照失败的原因。 


往期文章回顾:

《redis灵魂拷问:聊一聊AOF日志重写》

 《redis灵魂拷问:聊一聊redis底层数据结构》

《redis灵魂拷问:怎么搭建一个哨兵主从集群》


   欢迎关注个人公众号

                                                                    

最新回复(0)