Redis_持久化机制(AOF 和 RDB)

Redis把后端数据库中的数据存储在内存中,然后直接从内存中读取数据,速度很快。

但是存在问题:一旦服务器宕机,内存中的数据将全部丢失。

通过从后端数据库恢复这些数据,存在两个问题:一是,需要频繁访问数据库,会给数据库带来巨大的压力;二是,这些数据是从慢速数据库中读取出来的,性能肯定比不上从 Redis 中读取,导致使用这些数据的应用程序响应变慢。

Redis 的持久化主要有两大机制,即 AOF 日志和 RDB 快照。【Redis通过AOF日志避免丟失數據,通過RDB快照快速恢復數據】

目录

一、 AOF 日志(宕机了,如何避免数据丢失)

1、AOF作为写后日志的好处与风险

写后日志的好处:

写后日志的潜在风险:

2、AOF解决潜在风险的机制

回写机制:(依据对于高性能和高可靠的需求,选择回写机制)

重写机制:  (解决日志文件过大带来的性能问题,将命令多变一)

重写机制 通过子进程避免主线程阻塞

二、RDB快照(宕机了,如何实现快速恢复)

1、使用快照需要考虑的两个关键问题:

给哪些内存数据做快照?

怎么生成快照?是否会阻塞主线程? 提供两种选择

选择生成的频率? 平衡丢失的数据量和生成快照带来的开销

使用增量快照  解决通过提高全量快照频率来较少数据丢失量所造成的开销

快照时数据能修改吗?  

三、混合使用 AOF 日志和RDB快照   解决高频率RDB 和 过大AOF日志文件 所带来的开销


一、 AOF 日志(宕机了,如何避免数据丢失)

Redis核心技术与实战 - 04

1、AOF作为写后日志的好处与风险

AOF 里记录的是 Redis 收到的每一条命令,这些命令是以文本形式保存。AOF是写后日志,“写后”的意思是 Redis 是先执行命令,把数据写入内存,然后才记录日志。

写后日志的好处:

  • 日志不用验证所记录的命令的语法的准确性,只有正确执行的命令才会被记录,因此在根据日志恢复数据时候就不会出错。
  • 在命令执行后才记录日志,则不会阻塞当前的写操作。

写后日志的潜在风险:

  • 如果刚执行完一个命令,还没有来得及记日志就宕机了,那么这个命令和相应的数据就有丢失的风险。
  • AOF 虽然避免了对当前命令的阻塞,但可能会给下一个操作带来阻塞风险。这是因为,AOF 日志也是在主线程中执行的,如果在把日志文件写入磁盘时,磁盘写压力大,就会导致写盘很慢,进而导致后续的操作也无法执行了。

2、AOF解决潜在风险的机制

两个风险都是和 AOF 写回磁盘的时机相关的。这也就意味着,如果我们能够控制一个写命令执行完后 AOF 日志写回磁盘的时机,这两个风险就解除了。因此AOF提供了三种回写机制的选择。也就是 AOF 配置项 appendfsync 的三个可选值。

回写机制:(依据对于高性能和高可靠的需求,选择回写机制)

  1. Always,同步写回:每个写命令执行完,立马同步地将日志写回磁盘;
  2. Everysec,每秒写回:每个写命令执行完,只是先把日志写到 AOF 文件的内存缓冲区,每隔一秒把缓冲区中的内容写入磁盘;
  3. No,操作系统控制的写回:每个写命令执行完,只是先把日志写到 AOF 文件的内存缓冲区,由操作系统决定何时将缓冲区内容写回磁盘。

在使用过程中,可以根据系统对 高性能高可靠性 的要求,来选择使用哪种写回策略了。

重写机制: (解决日志文件过大带来的性能问题)

不仅回写策略会影响性能,随着接收的写命令越来越多,AOF 文件会越来越大。过大的日志文件也会影响性能。

过大日志带来的性能问题:

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

重写机制:

AOF 重写机制就是在重写时,Redis 根据数据库的现状创建一个新的 AOF 文件,也就是说,读取数据库中的所有键值对,然后对每一个键值对用一条命令记录它的写入。AOF 文件是以追加的方式,逐一记录接收到的写命令的。当一个键值对被多条写命令反复修改时,AOF 文件会记录相应的多条命令。但是,在重写的时候,是根据这个键值对当前的最新状态,为它生成对应的写入命令。这样一来,一个键值对原有的多条记录在重写日志中只用一条命令就行了。从而在日志恢复时,只需一条命令即可正确回复数据。

重写机制 通过子进程避免主线程阻塞

虽然 AOF 重写后,日志文件会缩小,但是,要把整个数据库的最新数据的操作日志都写回磁盘,仍然是一个非常耗时的过程。但是,和 AOF 日志由主线程写回不同,重写过程是由后台子进程 bgrewriteaof 来完成的,这也是为了避免阻塞主线程,导致数据库性能下降。

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

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

二、RDB快照(宕机了,如何实现快速恢复)

Redis核心技术与实战 - 05

内存快照:指的是内存中的数据在某一个时刻的状态记录。

对 Redis 来说,它实现类似照片记录效果的方式,就是把某一时刻的状态以文件的形式写到磁盘上,也就是快照。这样一来,即使宕机,快照文件也不会丢失,数据的可靠性也就得到了保证。这个快照文件就称为 RDB 文件,其中,RDB 就是 Redis DataBase 的缩写。

和 AOF 相比,RDB 记录的是某一时刻的数据,并不是操作,所以,在做数据恢复时,我们可以直接把 RDB 文件读入内存,很快地完成恢复。

1、使用快照需要考虑的两个关键问题:

  1. 对哪些数据做快照?这关系到快照的执行效率问题;
  2. 做快照时,数据还能被增删改吗?这关系到 Redis 是否被阻塞,能否同时正常处理请求。

给哪些内存数据做快照?

Redis 的数据都在内存中,为了提供所有数据的可靠性保证,它执行的是全量快照,也就是说,把内存中的所有数据都记录到磁盘中。

全量快照是会消耗性能的,并且Redis是单线程读写所以需要考虑是否会阻塞主线程,这就关系到是否会降低 Redis 的性能。

怎么生成快照?是否会阻塞主线程?

Redis 提供了两个命令来生成 RDB 文件,分别是 save 和 bgsave。

  • save:在主线程中执行,会导致阻塞;
  • bgsave:创建一个子进程,专门用于写入 RDB 文件,避免了主线程的阻塞,这也是 Redis RDB 文件生成的默认配置。

选择生成的频率?平衡丢失的数据量和生成快照带来的开销

即使通过bgsave可以避免阻塞主线程,但是频繁地执行全量快照,虽然可以减少宕机时丢失的数据,但也会带来两方面的开销。

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

使用增量快照

所谓增量快照,就是指,做了一次全量快照后,后续的快照只对修改的数据进行快照记录,这样可以避免每次全量快照的开销。但是增量快照需要“记住”被修改的数据,这个“记住”操作也会带来额外数据存储的空间开销。

快照时数据能修改吗?  

Redis 会使用 bgsave 对当前内存中的所有数据做快照,这个操作是子进程在后台完成的,这就允许主线程同时可以修改数据。如果主线程要修改一块数据,那么,这块数据就会被复制一份,生成该数据的副本。然后,bgsave 子进程会把这个副本数据写入 RDB 文件,而在这个过程中,主线程仍然可以直接修改原来的数据。

三、混合使用 AOF 日志和RDB快照

虽然跟 AOF 相比,快照的恢复速度快,但是,快照的频率不好把握,如果频率太低,两次快照间一旦宕机,就可能有比较多的数据丢失。如果频率太高,又会产生额外开销。

Redis 4.0 中提出了一个混合使用 AOF 日志和内存快照的方法。简单来说,内存快照以一定的频率执行,在两次快照之间,使用 AOF 日志记录这期间的所有命令操作。这样一来,快照不用很频繁地执行,这就避免了频繁 fork 对主线程的影响。而且,AOF 日志也只用记录两次快照间的操作,也就是说,不需要记录所有操作了,因此,就不会出现文件过大的情况了,也可以避免重写开销。

猜你喜欢

转载自blog.csdn.net/u013025748/article/details/113611926