Redis之RDB,AOF和集群同步讲解

1 Redis持久化

Redis数据是存储在内存中的,但是我们都知道内存的数据变化是很快的,也容易发生丢失,为了保证Redis数据不丢失,那就要把数据从内存存储到磁盘上,以便在服务器重启后还能够从磁盘中恢复原有数据,这就是Redis的数据持久化。
Redis数据持久化有三种方式:

  • AOF 日志(Append Only File,文件追加方式):记录所有的操作命令,并以文本的形式追加到文件中。
  • RDB快照(Redis DataBase):将某一个时刻的内存数据,以二进制的方式写入磁盘(早期默认方式)。
  • 混合持久化方式:Redis 4.0 新增了混合持久化的方式,集成了 RDBAOF 的优点

1.1 持久化

redis集群同步:


image.png

1.1.1 持久化流程

既然redis的数据可以保存在磁盘上,那么这个流程是什么样的呢?
要有下面五个过程:

  • 客户端向服务端发送写操作(数据在客户端的内存中)
  • 数据库服务端接收到写请求的数据(数据在服务端的内存中)
  • 服务端调用write这个系统调用,将数据往磁盘上写(数据在系统内存的缓冲区中)
  • 操作系统将缓冲区中的数据转移到磁盘控制器上(数据在磁盘缓存中)
  • 磁盘控制器将数据写到磁盘的物理介质中(数据真正落到磁盘上)

1.1.2 数据同步机制

对于多副本模式,Redis和关系型数据库一样,提供了主从库模式来保证数据副本的一致性。主从库之间采用的是读写分离的方式,即读操作可以被主库/从库接收,但是写操作只能先被主库接收执行然后才由主库同步给从库。

d733f1fdd141fa568545bf0eb6db04da_841d20f6f83d4500916b9068cb2b79f5.png

那么问题来了,为啥要用读写分离实现?

如果每次的修改请求都发到不同的实例上,要保证数据的一致性,就需要涉及到加锁和协商是否完成修改等操作,这会带来很大的性能开销。而如果所有的修改都只在主库上进行,就无需协调三个实例,只需要同步给从库,进而保持数据一致性。

1.1.3 Redis主从库同步流程详解

假设现在我们有两个实例,分别是主库实例1(172.16.19.3)和实例2(172.16.19.5),我们的目标就是让实例2成为实例1的从库,并进行数据同步

1.1.3.1 第一次同步过程

在实战中,只需要实例2的shell中执行以下命令就可以将实例2作为实例1的从库,并从实例1上复制数据

replicaof 172.16.19.3 6369

虽然就这一个命令真简单,而在这背后,Redis偷偷摸摸地进行了三个阶段的操作,如下图所示


07c5b75e181bca3a005f35e6f742bc61_740bcfc3b03b4a71844072763be8b30b.jpeg
  • 阶段1:从库向主库发送psync命令,表示进行数据同步。该命令格式如下所示:
    命令格式:psync runID offset# psync ? -1
    其中代表从库并不知道主库的runID,-1表示第一次复制
    主库收到psync命令确认后,会向从库发送一个FULLERSYNC的响应命令,并带上主库的runID和目前的复制进度offset
    命令格式:FULLERSYNC runID offset
    FULLERSYNC代表全量复制,一般用于第一次数据同步
  • 阶段2:主库通过发送RDB文件给从库,从库收到后在本地完成数据加载。
    需要注意的点:
    • 主库会首先执行一次bgsavebgsave不会阻塞主线程)生成RDB文件,然后才发送给从库。
    • 从库会首先清空已有的数据,然后再加载RDB数据,因为在同步之前可能保存了其他数据,不清除的话可能会数据不一致。
    • 主库在同步数据给从库中产生的写操作会用专门的replication buffer记录,然后在第三个阶段同步过去。
  • 阶段3:主库将第二阶段执行过程收到的新的写操作命令,同步给从库。
    在实现中,主库会将新收到的写操作放到replication buffer中记录下来,然后将这些操作修改发给从库,从库收到后再重新执行一遍这些操作。

以上三个阶段完成之后,主从库就算完成了一次数据同步。

1.1.3.2 为什么用RDB不用AOF

Redis主库在向从库同步数据时使用的RDB文件,那么AOF记录的操作命令更全,相比RDB丢失的数据更少,为什么主库用RDB不用AOF呢?

  • RDB读取速度相对较快,从库可以快速完成RDB的读取,然后再去消费replication buffer的数据完成一次同步。而如果使用AOF,其体积大读取速度慢,且需要更大空间的replication buffer,对于一个主节点多个从节点来说的话,内存的占用就会更大;
  • AOFAppend追加模式,同时读写需要考虑并发安全问题,并且AOF是文本文件,体积较大,浪费网络带宽

1.1.3.3 主从级联模式降低主库压力

主从库同步过程中,主库需要完成两个耗时的操作:生成RDB文件 和 传输RDB文件。现实场景中,从库一般都会有多个,如果都要和主库同步的话,会造成主库的性能压力 和 网络压力。

主库需要fork子进程来生成RDB文件,这个fork操作是会阻塞主线程处理正常请求的,虽然后续的bgsave过程不会阻塞主线程。
此外,传输RDB文件也会占用主库服务器的网络带宽。

Redis提供了主从级联模式,也就是所谓的主-从-从模式。
主-从-从模式下,新增的从库可以设置从 集群中的某一个从库 中进行数据同步,从而避免每次都从主库进行同步,降低主库的资源消耗,保证系统的稳定性。

比如,在实际中通常会手动选择一个 内存配置较高的 从库 来作为同步源,其他新的从库加入后可以从这个从库中同步,建立主从关系。例如,下面的命令就可以实现新增从库和某一个从库建立主从关系:
replicaof 所选从库ID 6379

具体的示意图如下图所示:


ecdc9974a04fed5951ad2b378746a635_6469a66db5534b14942b3e8e4e3b3e7b.jpeg

1.1.3.4 全量同步后的增量同步

主从库通过FULLERSYNC进行全量复制同步 + 主从级联模式分担主库压力 之后,Redis的主从库之间就会一直维护一个长连接来进行增量的命令操作同步,这个过程又被称之为基于长连接的命令传播
为何选择长连接?因为可以避免频繁建立连接的开销。
虽然长连接很方便,但也存在一个风险点:主从库网络断了或 阻塞了。这个风险可能导致的问题就是:主从库之间数据无法保持一致,客户端可能从读库读到过时的数据。
当然,Redis早就已经为我们想好了解决方案,不过得分为两个版本来看:

  • Redis 2.8之前,如果出现了网络闪断,Redis主从库间会重新进行一次全量复制。当然,全量复制就意味着有很大的开销。
  • Redis 2.8之后,如果出现了网络闪断,Redis主从库间会采用增量复制的方式继续同步。可以看到,增量复制肯定比全量复制开销要小得多。主要用于网络中断等情况后的复制,只将中断期间 mater 执行的写命令发送给 slave,与全量复制相比更加高效。

这里的增量复制的核心要点就在于Redis引入了repl_backlog_buffer缓冲区,现在我们就来看看这个repl_backlog_buffer到底是个啥。
repl_backlog_buffer是一个环形缓冲区,主库会记录自己写到的位置,从库则会记录自己已经读到的位置。下图展示了repl_backlog_buffer的示意图:

c417e9a96fe7f1c8bdfb36eed0d21fd3_31318dd75d6f4a5ab56a4ebe6caa8f33.jpeg

可以看到,正常情况下,主从库的偏移量基本相等。随着主库不断接收新的写操作,它在缓冲区中的写位置会逐步偏离起始位置。对主库来说,对应的偏移量就是 master_repl_offset,只要主库的新写操作越多,这个值也就越大。同理,从库在复制完写操作命令后,它在缓冲区中的读位置也开始逐步偏移起始位置。对从库来说,其对应的已复制偏移量就是 slave_repl_offset
当网络闪断异常情况下,主库可能会接收到新的写操作命令,因此,可以看出,主库的偏移量master_repl_offset > 从库的偏移量slave_repl_offset。那么,此时就只需要把 master_repl_offset 和 slave_repl_offset 之间的命令操作同步给从库就ok了。

综上所述,增量同步的过程整体如下:

0e4fcaacd2174fa1c0e9d526ca3ae54f_dfb76d1c4e0843dd8407fcf3792d3ead.jpeg

Redis 7.0 之后,采用了共享缓冲区的设计。因为不管是全量复制还是增量复制,当写请求到达 master 时,指令会分别写入所有 slavereplication buffer 以及 repl_backlog_buffer。重复保存,太浪费内存了。
共享缓冲区:既然存储内容是一样,直接的做法就是主从复制在命令传播时,将这些写命令放在一个全局的复制缓冲区中,多个 slave 共享这份数据,不同 slave 引用缓冲区的不同内容。

1.1.3.5 repl_backlog_buffer扩展

在增量复制过程中,需要注意的点:repl_backlog_buffer是一个环形缓冲区,在缓冲区被写满了之后,主库再次写入时就会覆盖掉之前写入的操作。
那么问题来了,如果从库读取的速度很慢,就有可能出现从库读取到了不一致的数据。如何解决?
Redis提供了一个 repl_backlog_size 的参数,它与缓冲区的空间大小紧密相关。在实际中,一般其设置为:repl_backlog_size = 缓冲区空间大小 * 2,这样可以降低由于读库消费速度慢导致的数据不一致。
缓冲空间的计算公式是:

缓冲空间大小 = 主库写入命令速度 * 操作大小 - 主从库间网络传输命令速度 * 操作大小

但是,如果并发请求量特别大,两倍的缓冲区空间都不够用,主从库仍然存在不一致的风险,那么此时,可能需要根据Redis所在服务器的性能指标(主要是内存资源)再增加一些 repl_backlog_size 值。

1.2 RDB机制

RDB其实就是把数据以快照的形式保存在磁盘上。什么是快照呢,你可以理解成把当前时刻的数据拍成一张照片保存下来。
RDB持久化是指在指定的时间间隔内将内存中的数据集快照写入磁盘。也是 默认的持久化方式(早期),这种方式是就是将内存中数据以快照的方式写入到二进制文件中,默认的文件名为dump.rdb
RDB采用的是内存快照的方式,它记录的是某一时刻的数据,而不是操作,所以采用RDB方法做故障恢复时只需要直接把RDB文件读入内存即可,实现快速恢复。

在我们安装了redis之后,所有的配置都是在redis.conf文件中,里面保存了RDBAOF两种持久化机制的各种配置

既然RDB机制是通过把某个时刻的所有数据生成一个快照来保存,那么就应该有一种触发机制,是实现这个过程。对于RDB来说,提供了三种机制:savebgsave自动化。我们分别来看一下

1.2.1 save触发方式

该命令会阻塞当前Redis服务器,执行save命令期间,Redis不能处理其他命令,直到RDB过程完成为止。具体流程如下:

image.png

执行完成时候如果存在老的RDB文件,就把新的替代掉旧的。我们的客户端可能都是几万或者是几十万,这种方式显然不可取

1.2.2 bgsave

1.2.2.1 bgsave触发方式

执行该命令时,Redis会在后台异步进行快照操作,快照同时还可以响应客户端请求。具体流程如下:

image.png

具体操作是Redis进程执行fork操作创建子进程,RDB持久化过程由子进程负责,完成后自动结束。阻塞只发生在fork阶段,一般时间很短。基本上Redis内部所有的RDB操作都是采用bgsave命令即默认配置

在执行快照的同时,Redis 会借助操作系统提供的写时复制技术(Copy-On-Write, COW),正常处理写操作。bgsave 子进程是由主线程 fork 生成的,可以共享主线程的所有内存数据。bgsave 子进程运行后,开始读取主线程的内存数据,并把它们写入 RDB 文件

Redis是怎么解决在bgsave做快照的时候允许数据修改呢?
这里主要是利用bgsave的子线程实现的,具体操作如下:
如果主线程执行读操作,则主线程和 bgsave 子进程互相不影响;
如果主线程执行写操作,则被修改的数据会复制一份副本,然后,主线程在这个数据副本上进行修改。同时,bgsave 子进程可以继续把原来的数据 写入 RDB 文件,在这个过程中,主线程仍然可以直接修改原来的数据

image.png

虽然 bgsave 执行时不阻塞主线程,但是,如果频繁地执行全量快照,也会带来两方面的开销:

  • 一方面,频繁将全量数据写入磁盘,会给磁盘带来很大压力,多个快照竞争有限的磁盘带宽,前一个快照还没有做完,后一个又开始做了,容易造成恶性循环(所以,在 Redis 中如果有一个 bgsave 在运行,就不会再启动第二个 bgsave 子进程)
  • 另一方面,bgsave 子进程需要通过 fork 操作从主线程创建出来。虽然,子进程在创建后不会再阻塞主线程,但是,fork 这个创建过程本身会阻塞主线程 ,而且 主线程的内存越大,阻塞时间越长

需要注意RedisRDB 的执行频率非常重要,因为这会影响快照数据的完整性以及 Redis 的稳定性,所以在 Redis 4.0 后,增加了 AOFRDB 混合的数据持久化机制: 把数据以 RDB 的方式写入文件,再将后续的操作命令以 AOF 的格式存入文件,既保证了 Redis 重启速度,又降低数据丢失风险,内存快照以一定的频率执行,在两次快照之间,使用 AOF 日志记录这期间的所有命令操作

1.2.2.2 写时复制

点击此次了解Linux中写时复制技术
执行 bgsave 命令的时候,会通过 fork() 创建子进程,此时子进程和父进程是共享同一片内存数据的,因为创建子进程的时候,会复制父进程的页表,但是页表指向的物理内存还是一个,此时如果主线程执行读操作,则主线程和 bgsave 子进程互相不影响。

8f8a020dbd534d09970fbcb911023941_6b1e052efb2344f9a94c851b0ae0dd22.png

如果主线程执行写操作,则被修改的数据会复制一份副本,然后 bgsave 子进程会把该副本数据写入 RDB 文件,在这个过程中,主线程仍然可以直接修改原来的数据。

b518b4c5cfc0c94127d3a4afc013fca4_05e9e9c4814642d39d2a9896a62356d4.png

1.2.3 自动触发

自动触发是由我们的配置文件来完成的。在redis.conf配置文件中,里面有如下配置,我们可以去设置:

  • save:这里是用来配置触发 RedisRDB 持久化条件,也就是什么时候将内存中的数据保存到硬盘。比如save m n。表示m秒内数据集存在n次修改时,自动触发bgsave
    默认如下配置:
    表示900 秒内如果至少有 1key的值变化,则保存save 900 1
    表示300 秒内如果至少有 10key 的值变化,则保存save 300 10
    表示60 秒内如果至少有 10000key 的值变化,则保存save 60 10000
    不需要持久化,那么你可以注释掉所有的 save行来停用保存功能。
  • stop-writes-on-bgsave-error :默认值为yes。当启用了RDB且最后一次后台保存数据失败,Redis是否停止接收数据。这会让用户意识到数据没有正确持久化到磁盘上,否则没有人会注意到灾难(disaster)发生了。如果Redis重启了,那么又可以重新开始接收数据了
  • rdbcompression :默认值是yes。对于存储到磁盘中的快照,可以设置是否进行压缩存储。
  • rdbchecksum :默认值是yes。在存储快照后,我们还可以让redis使用CRC64算法来进行数据校验,但是这样做会增加大约10%的性能消耗,如果希望获取到最大的性能提升,可以关闭此功能。
  • dbfilename :设置快照的文件名,默认是 dump.rdb
  • dir:设置快照文件的存放路径,这个配置项一定是个目录,而不能是文件名

1.2.4 RDB的优势和劣势

1.2.4.1 优势

RDB文件紧凑,全量备份,非常适合用于进行备份和灾难恢复。
生成RDB文件的时候,redis主进程会fork()一个子进程来处理所有保存工作,主进程不需要进行任何磁盘IO操作。
RDB在恢复大数据集时的速度比 AOF 的恢复速度要快。

1.2.4.2 劣势

RDB快照是一次全量备份,存储的是内存数据的二进制序列化形式,存储上非常紧凑。当进行快照持久化时,会开启一个子进程专门负责快照持久化,子进程会拥有父进程的内存数据,父进程修改内存子进程不会反应出来,所以在快照持久化期间修改的数据不会被保存,可能丢失数据。

需要注意,RedisRDB 的执行频率非常重要,因为这会影响快照数据的完整性以及 Redis 的稳定性,所以在 Redis 4.0 后,增加了 AOFRDB 混合的数据持久化机制: 把数据以 RDB 的方式写入文件,再将后续的操作命令以 AOF 的格式存入文件,既保证了 Redis 重启速度,又降低数据丢失风险

1.3 AOF机制

全量备份总是耗时的,有时候我们提供一种更加高效的方式AOF,工作机制很简单,redis会将每一个收到的写命令都通过write函数追加到文件中。通俗的理解就是日志记录

AOF采用的是写后日志的方式,Redis先执行命令把数据写入内存,然后再记录日志到文件中。AOF日志记录的是操作命令,不是实际的数据,如果采用AOF方法做故障恢复时需要将全量日志都执行一遍

image.png

AOF 里记录的是 Redis 收到的每一条命令,这些命令是以文本形式保存的。
我们以 Redis 收到set testkey testvalue命令后记录的日志为例,看看 AOF 日志的内容。其中,*3 表示当前命令有三个部分,每部分都是由 $+数字 开头,后面紧跟着具体的命令、键或值。这里,数字表示这部分中的命令、键或值一共有多少字节。例如,$3 set 表示这部分有 3 个字节,也就是set命令。

image.png

1.3.1 写后日志优势和风险

AOF采用的是写后日志的方式,我们平时用的MySQL则采用的是 写前日志,那 Redis为什么要先执行命令,再把数据写入日志呢?
这个主要是由于Redis在写入日志之前,不对命令进行语法检查,所以只记录执行成功的命令,避免出现记录错误命令的情况,而且在命令执行后再写日志不会阻塞当前的写操作

后写日志的风险:

  • 数据可能会丢失:如果 Redis 刚执行完命令,此时发生故障宕机,会导致这条命令存在丢失的风险
    • 如果此时 Redis 是用作缓存,还可以从后端数据库重新读入数据进行恢复。
    • 如果 Redis 是直接用作数据库的话,此时,因为命令没有记入日志,所以就无法用日志进行恢复了。
  • 可能阻塞其他操作:AOF 日志其实也是在主线程中执行,所以当 Redis 把日志文件写入磁盘的时候,还是会阻塞后续的操作无法执行,(即:AOF 虽然避免了对当前命令的阻塞,但可能会给下一个操作带来阻塞风险)
    AOF 日志也是在主线程中执行(写回策略为 always 时),如果在把日志文件写入磁盘时,磁盘写压力大,就会导致写盘很慢,进而导致后续的操作也无法执行了。

1.3.2 AOF三种触发机制

  • 每修改同步always:每个写命令执行完,立马同步地将日志写回磁盘,同步持久化,每次发生数据变更会被立即记录到磁盘,性能较差但数据完整性比较好
  • 每秒同步everysec:每个写命令执行完,只是先把日志写到 AOF 文件的内存缓冲区,每隔一秒把缓冲区中的内容写入磁盘
    异步操作,每秒记录,如果一秒内宕机,有数据丢失,
  • 不同步no:每个写命令执行完,只是先把日志写到 AOF 文件的内存缓冲区,由操作系统决定何时将缓冲区内容写回磁盘
配置项 写回时机 优点 缺点
Always 同步写回 可靠性高,数据基本不丢失 每个写命令都有落盘,性能影响较大
Everysec 每秒写回 性能适中 宕机时丢失1秒内的数据
No 操作系统控制的写回 性能好 宕机时丢失数据较多

我们就可以根据系统对高性能和高可靠性的要求,来选择使用哪种写回策略了。

  • 想要获得高性能,就选择 No 策略;
  • 想要得到高可靠性保证,就选择 Always 策略;
  • 允许数据有一点丢失,又希望性能别受太大影响的话,那么就选择 Everysec 策略

1.3.3 文件重写

1.3.3.1 重写的作用

AOF 是以文件的形式在记录接收到的所有写命令。随着接收的写命令越来越多,AOF 文件会越来越大。这也就意味着,我们一定要小心 AOF 文件过大带来的性能问题,主要在于以下三个方面:

  • 文件系统本身对文件大小有限制,无法保存过大的文件;
  • 如果文件太大,之后再往里面追加命令记录的话,效率也会变低;
  • 如果发生宕机,AOF 中记录的命令要一个个被重新执行,用于故障恢复,如果日志文件太大,整个恢复过程就会非常缓慢,这就会影响到 Redis 的正常使用。

AOF 重写机制就是在重写时,Redis 根据数据库的现状创建一个新的 AOF 文件,也就是说,读取数据库中的所有键值对,然后对每一个键值对用一条命令记录它的写入 。重写机制具有多变一功能。所谓的多变一,也就是说,旧日志文件中的多条命令,在重写后的新日志中变成了一条命令。

image.png

1.3.3.2 重写的过程

AOF 日志由主线程写回不同,重写过程是由 后台子进程 bgrewriteaof 来完成的,这也是为了避免阻塞主线程 ,导致数据库性能下降。
可以把重写的过程总结为 一个拷贝,两处日志

  • 一个拷贝:就是指,每次执行重写时,主线程 fork 出后台的 bgrewriteaof 子进程。此时,fork 会把主线程的内存拷贝一份给 bgrewriteaof 子进程,这里面就包含了数据库的最新数据。然后,bgrewriteaof 子进程就可以在不影响主线程的情况下,逐一把拷贝的数据写成操作,记入重写日志。
  • 第一处日志:指的是因为主线程未阻塞,仍然可以处理新来的操作,Redis会把这个操作写到它的缓冲区。这样一来,即使宕机了,这个 AOF 日志的操作仍然是齐全的,可以用于恢复。
  • 第二处日志:就是指新的 AOF 重写日志。这个操作也会被写到重写日志的缓冲区。这样,重写日志也不会丢失最新的操作。等到拷贝数据的所有操作记录重写完成后,重写日志记录的这些最新操作也会写入新的 AOF 文件,以保证数据库最新状态的记录。

此时,我们就可以用新的 AOF 文件替代旧文件了。

image.png

为了压缩aof的持久化文件。redis提供了bgrewriteaof命令。将内存中的数据以命令的方式保存到临时文件中,同时会fork出一条新进程来将文件重写。

image.png

设置 AOF 重写策略,例如配置auto-aof-rewrite-percentageauto-aof-rewrite-min-size,让Redis自动在文件增长到一定比例或超过最小尺寸时触发AOF重写。

1.3.3.3 总结

总结来说,每次 AOF 重写时,Redis 会先执行一个内存拷贝,用于重写;然后,使用两个日志保证在重写过程中,新写入的数据不会丢失。而且,因为 Redis 采用子进程进行日志重写,所以,这个过程并不会阻塞主线程 。

正因为记录的是操作命令,而不是实际的数据,所以,用 AOF 方法进行故障恢复的时候,需要逐一把操作日志都执行一遍。如果操作日志非常多,Redis 就会恢复得很缓慢,影响到正常使用

1.3.4 AOF增量同步

AOF增量同步:配置aof-rewrite-incremental-fsync选项,可以控制在AOF重写过程中增量地进行fsync操作,从而减少AOF文件过大时的同步操作开销。

这个选项的作用是控制Redis在执行AOF重写时对磁盘的同步频率。默认情况下,当进行AOF重写时,Redis会在重写完成后执行一次完整的fsync操作来确保AOF文件的持久性,这可能会导致性能下降,特别是对于大型AOF文件而言。启用 aof-rewrite-incremental-fsync 后,Redis会在重写AOF文件的过程中增量地进行fsync操作,而不是在重写完成后进行一次完整的fsync操作,这样可以降低磁盘I/O压力,提高性能。

要启用 aof-rewrite-incremental-fsync,你需要在Redis配置文件中设置该选项为 yes:

aof-rewrite-incremental-fsync yes

启用此选项后,Redis在进行AOF重写时将采用增量fsync操作,以降低同步操作的开销。
这样,当AOF文件过大时,Redis就可以更加高效地进行AOF重写,减少同步操作对性能的影响

1.3.5 优缺点

1.3.5.1 优点

  • AOF可以更好的保护数据不丢失,一般AOF会每隔1秒,通过一个后台线程执行一次fsync操作,最多丢失1秒钟的数据。
  • AOF日志文件没有任何磁盘寻址的开销,写入性能非常高,文件不容易破损。
  • AOF日志文件即使过大的时候,出现后台重写操作,也不会影响客户端的读写。
  • AOF日志文件的命令通过非常可读的方式进行记录,这个特性非常适合做灾难性的误删除的紧急恢复。比如某人不小心用flushall命令清空了所有数据,只要这个时候后台rewrite还没有发生,那么就可以立即拷贝AOF文件,将最后一条flushall命令给删了,然后再将该AOF文件放回去,就可以通过恢复机制,自动恢复所有数据

1.3.5.2 缺点

  • 对于同一份数据来说,AOF日志文件通常比RDB数据快照文件更大
  • AOF开启后,支持的写QPS会比RDB支持的写QPS低,因为AOF一般会配置成每秒fsync一次日志文件,当然,每秒一次fsync,性能也还是很高的
  • 以前AOF发生过bug,就是通过AOF记录的日志,进行数据恢复的时候,没有恢复一模一样的数据出来

1.4 两者混合

虽然 bgsave 执行时不阻塞主线程,但是,如果频繁地执行全量快照,也会带来两方面的开销。

  • 一方面,频繁将全量数据写入磁盘,会给磁盘带来很大压力,多个快照竞争有限的磁盘带宽,前一个快照还没有做完,后一个又开始做了,容易造成恶性循环(所以,在 Redis 中如果有一个 bgsave 在运行,就不会再启动第二个 bgsave 子进程)
  • 另一方面,bgsave 子进程需要通过 fork 操作从主线程创建出来。虽然,子进程在创建后不会再阻塞主线程,但是,fork 这个创建过程本身会阻塞主线程,而且 主线程的内存越大,阻塞时间越长

RDBAOF到底该如何选择
选择的话,两者加一起才更好。因为两个持久化机制你明白了,剩下的就是看自己的需求了,需求不同选择的也不一定,但是通常都是结合使用。有一张图可供总结:

image.png

需要注意RedisRDB 的执行频率非常重要,因为这会影响快照数据的完整性以及 Redis 的稳定性,所以在 Redis 4.0 后,增加了 AOFRDB 混合的数据持久化机制,简单来说:内存快照以一定的频率执行,在两次快照之间,使用 AOF 日志记录这期间的所有命令操作,这样一来,快照不用很频繁地执行,这就避免了频繁 fork 对主线程的影响。而且,AOF 日志也只用记录两次快照间的操作,也就是说,不需要记录所有操作了,因此,就不会出现文件过大的情况了,也可以避免重写开销

image.png

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 205,033评论 6 478
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 87,725评论 2 381
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 151,473评论 0 338
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,846评论 1 277
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,848评论 5 368
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,691评论 1 282
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 38,053评论 3 399
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,700评论 0 258
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 42,856评论 1 300
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,676评论 2 323
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,787评论 1 333
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,430评论 4 321
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 39,034评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,990评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,218评论 1 260
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 45,174评论 2 352
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,526评论 2 343

推荐阅读更多精彩内容