Redis series (three): persistence mechanism of Redis (RDB, AOF)

This blog is Redis series of three, two kinds mainly on Redis persistence mechanism under: RDB and AOF.

This series of former two can click on the link below to view:

Redis series (a): Redis Introduction and installation environment .

Redis Series (B): five kinds of data structures of commands and Redis

1. Why do you need to persist?

Redis is because the in-memory database, which will own the data stored in the memory inside, once Redis server process to exit or shut down a computer running Redis server, Redis server data will be lost.

To avoid data loss, so Redis provides a persistence mechanism to save the data stored in memory to disk for the server process to exit or Redis Redis server computer running down leads to data loss, before a quick recovery storage Redis data in memory.

Redis offers two persistent way, namely:

  1. RDB endurance of
  2. AOF persistence

Next, we 11 Xiangjie.

2. RDB endurance of

RDB persistent data is saved in a point in time to a RDB Redis file, as follows:

Based on the above properties RDB persistent, so RDB also called persistent snapshot persistence.

The compressed file is a binary file, the data can be restored Redis RDB is generated by the document file, as follows:

2.1 Creating RDB file

Redis provides two commands to create RDB files, one is SAVE, the other is BGSAVE.

SAVE command Redis server process will block until the RDB file is created, the server during the process blocked, the server can not process any command requests as follows:

BGSAVE command derive a child process, then the responsibility of the child process created RDB file server process (parent process) continues to process the request command, as follows:

Described above is the difference between these two commands, here is the key, often ask to interview .

Because BGSAVE command can be executed without blocking the server process, it is recommended to use BGSAVE command.

We can perform a manual command, as shown in the screenshot above, but it is recommended to set save options under Redis server configuration file, so that the server automatically performs a BGSAVE command from time to time.

We can save storage conditions set multiple options, as long as any of the conditions are met, the server will perform BGSAVE command.

By default save option settings are as follows:

save 900 1

save 300 10

save 60 10000

Condition indicates default configuration, as long as any of the following three conditions 1, bgsave command will be executed:

  • In the server 900s (i.e., 15 minutes), the database is at least one of revision
  • 300S in the server (i.e., 5 minutes), the database is to modify at least 10
  • Server within 60s (i.e., 1 minute), the database is to modify at least 10,000 times

When conditional execution BGSAVE command output log as shown below:

RDB generated file saved according to Redis configuration file name and path, the two related configuration is as follows:

As shown in (screenshot native Windows, Linux environment will be slightly different path) RDB file finally generated as follows:

2.2 Loading RDB file

First, we must be clear that the purpose of loading the file is to RDB data previously stored in the reducing Redis Redis server process after the restart.

Then, Redis loaded RDB file and there is no specific command, but automatically executed when the Redis server starts.

Also, if loads when Redis server starts RDB file server also depends on whether the AOF persistent feature is enabled, to determine the specific logic:

  1. Only when AOF persistence feature is turned off, the server will use RDB file to restore data.
  2. If the server is turned AOF persistence function, the server will give priority to the use of AOF file to restore data.

Analyzing logic as shown above:

By default, AOF Redis server persistence feature is turned off, so Redis server at startup will load RDB file,

Start log as follows:

2.3 Server Status

Create and load RDB file, the server status may present there are the following three:

  1. 当执行SAVE命令时,Redis服务器会被阻塞,此时客户端发送的所有命令请求都会被阻塞,只有在服务器执行完SAVE命令,重新开始接受命令请求之后,客户端发送的命令请求才会被处理。
  2. 当执行BGSAVE命令时,Redis服务器不会被阻塞,Redis服务器仍然可以继续处理客户端发送的命令请求。
  3. 服务器在载入RDB文件期间,会一直处于阻塞状态,直到RDB文件载入成功。

3. AOF持久化

AOF持久化是通过保存Redis服务器所执行的写命令来记录数据库数据的,如下图所示:

默认情况下,AOF持久化功能是关闭的,如果想要打开,可以修改下图所示的配置:

举个例子,假设Redis中还没有存储任何数据,我们执行了如下所示的命令:

然后我们会发现Redis服务器生成了1个名为appendonly.aof的文件,打开该文件,我们可以看到上面执行的3个写命令都存储在该文件中:

3.1 AOF持久化的实现

当AOF持久化功能处于打开状态时,Redis服务器在执行完一个写命令之后,会以协议格式(如上面截图中AOF文件里保存写命令的格式)将被执行的写命令追加到服务器状态的AOF缓冲区的末尾,然后Redis服务器会根据配置文件中appendfsync选项的值来决定何时将AOF缓冲区中的内容写入和同步到AOF文件里面。

appendfsync选项有以下3个值:

  1. always

    从安全性来说,always是最安全的(丢失数据最少),因为即使出现故障停机,数据库也只会丢失一个事件循环中所产生的命令数据。

    从效率来说,always的效率最慢,因为服务器在每个事件循环都要将AOF缓冲区中的所有内容写入到AOF文件,并且同步AOF文件。

  2. everysec

    从安全性来说,everysec模式下,即使出现故障停机,数据库只会丢失一秒钟的命令数据。

    从效率来说,everysec模式足够快,因为服务器在每个事件循环都要将AOF缓冲区中的所有内容写入到AOF文件,并且每隔一秒就要在子线程中对AOF文件进行同步。

  3. no

    从安全性来说,no模式下,如果出现故障停机,数据库会丢失上次同步AOF文件之后的所有写命令数据,具有不确定性,因为服务器在每个事件循环都要将AOF缓冲区中的所有内容写入到AOF文件,至于何时对AOF文件进行同步,则由操作系统控制。

    从效率来说,no模式和everysec模式的效率差不多。

appendfsync选项的默认值是everysec,也推荐使用这个值,因为既保证了效率又保证了安全性。

3.2 载入AOF文件

因为AOF文件包含了重建数据库所需的所有写命令,所以Redis服务器只要读入并重新执行一遍AOF文件里面保存的写命令,就可以还原Redis服务器关闭之前的数据。

Redis读取AOF文件并还原数据库的详细步骤如下:

  1. 创建一个不带网络连接的伪客户端

    因为Redis的命令只能在客户端上下文中执行,而载入AOF文件时所使用的命令直接来源于AOF文件而不是网络连接,所以服务器使用了一个没有网络连接的伪客户端来执行AOF文件保存的写命令。

    伪客户端执行命令的效果和带网络连接的客户端执行命令的效果完全一样。

  2. 从AOF文件中分析并读取出一条写命令。

  3. 使用伪客户端执行被读取出的写命令。

  4. 一直执行步骤2和步骤3,直到AOF文件中的所有写命令都被执行完毕。

以上步骤如下图所示:

如果Redis服务器开启了AOF持久化功能,那么Redis服务器在启动时会载入AOF文件,

启动日志如下所示:

3.3 AOF重写

因为AOF持久化是通过保存被执行的写命令来记录数据库数据的,所以随着Redis服务器运行时间的增加,AOF文件中的内容会越来越多,文件的体积会越来越大,如果不做控制,会有以下2点坏处:

  1. 过多的占用服务器磁盘空间,可能会对Redis服务器甚至整个宿主计算机造成影响。
  2. AOF文件的体积越大,使用AOF文件来进行数据库还原所需的时间就越多。

举个例子,在客户端执行如下命令:

为了记录这个list键的状态,AOF文件就需要保存上面执行的6条命令。

为了解决AO文件体积越来越大的问题,Redis提供了AOF文件重写功能,即Redis服务器会创建一个新的AOF文件来替代现有的AOF文件,新旧两个AOF文件所保存的数据库数据相同,但新AOF文件不会包含任何浪费空间的冗余命令,所以新AOF文件的体积通常会比旧AOF文件的体积要小很多。

3.3.1 AOF重写的实现原理

AOF文件重写并不需要对现有的AOF文件进行任何读取、分析或者写入操作,而是通过读取服务器当前的数据库数据来实现的。

仍然以上面的list键为例,旧的AOF文件保存了6条命令来记录list键的状态,但list键的结果是“C” "D" "E" "F" "G"这样的数据,所以AOF文件重写时,可以用一条RPUSH list “C” "D" "E" "F" "G"命令来代替之前的六条命令,这样就可以将保存list键所需的命令从六条减少为一条了。

按照上面的原理,如果Redis服务器存储的键值对足够多,AOF文件重写生成的新AOF文件就会减少很多很多的冗余命令,进而大大减小了AOF文件的体积。

综上所述,AOF文件重写功能的实现原理为:

首先从数据库中读取键现在的值,然后用一条命令去记录键值对,代替之前记录这个键值对的多条命令。

3.3.2 AOF后台重写

因为AOF文件重写会进行大量的文件写入操作,所以执行这个操作的线程将被长时间阻塞。

因为Redis服务器使用单个线程来处理命令请求,所以如果由服务器进程直接执行这个操作,那么在重写AOF文件期间,服务器将无法处理客户端发送过来的命令请求。

为了避免上述问题,Redis将AOF文件重写功能放到子进程里执行,这样做有以下2个好处:

  1. 子进程进行AOF文件重写期间,服务器进程(父进程)可以继续处理命令请求。
  2. 子进程带有服务器进程的数据副本,使用子进程而不是线程,可以在避免使用锁的情况下,保证数据的安全性。

AOF后台重写的步骤如下所示:

  1. 服务器进程创建子进程,子进程开始AOF文件重写

  2. 从创建子进程开始,服务器进程执行的所有写命令不仅要写入AOF缓冲区,还要写入AOF重写缓冲区

    写入AOF缓冲区的目的是为了同步到原有的AOF文件。

    写入AOF重写缓冲区的目的是因为子进程在进行AOF文件重写期间,服务器进程还在继续处理命令请求,

    而新的命令可能会对现有的数据库进行修改,从而使得服务器当前的数据库数据和重写后的AOF文件所

    保存的数据库数据不一致。

  3. 子进程完成AOF重写工作,向父进程发送一个信号,父进程在接收到该信号后,会执行以下操作:

    1.将AOF重写缓冲区中的所有内容写入到新AOF文件中,这样就保证了新AOF文件所保存的数据库数据和服务器当前的数据库数据是一致的。

    2.对新的AOF文件进行改名,原子地覆盖现有的AOF文件,完成新旧两个AOF文件的替换。

Redis提供了BGREWRITEAOF命令来执行以上步骤,如下图所示:

执行完成后,打开appendonly.aof文件,发现保存list键的命令从六条变为了一条:

除了手动执行BGREWRITEAOF命令外,Redis还提供了2个配置项用来自动执行BGREWRITEAOF命令:

auto-aof-rewrite-percentage 100

auto-aof-rewrite-min-size 64mb

该配置表示,当AOF文件的体积大于64MB,并且AOF文件的体积比上一次重写之后的体积大了至少一倍(100%),Redis将自动执行BGREWRITEAOF命令。

4. RDB持久化、AOF持久化的区别

通过上面的讲解,我们会发现Redis提供的2种持久化方法是有区别的,可以总结为以下4点:

  1. 实现方式
  2. 文件体积
  3. 安全性
  4. 优先级

接下来一一讲解。

4.1 实现方式

RDB持久化是通过将某个时间点Redis服务器存储的数据保存到RDB文件中来实现持久化的。

AOF持久化是通过将Redis服务器执行的所有写命令保存到AOF文件中来实现持久化的。

4.2 文件体积

由上述实现方式可知,RDB持久化记录的是结果,AOF持久化记录的是过程,所以AOF持久化生成的AOF文件会有体积越来越大的问题,Redis提供了AOF重写功能来减小AOF文件体积。

4.3 安全性

AOF持久化的安全性要比RDB持久化的安全性高,即如果发生机器故障,AOF持久化要比RDB持久化丢失的数据要少。

因为RDB持久化会丢失上次RDB持久化后写入的数据,而AOF持久化最多丢失1s之内写入的数据(使用默认everysec配置的话)。

4.4 优先级

由于上述的安全性问题,如果Redis服务器开启了AOF持久化功能,Redis服务器在启动时会使用AOF文件来还原数据,如果Redis服务器没有开启AOF持久化功能,Redis服务器在启动时会使用RDB文件来还原数据,所以AOF文件的优先级比RDB文件的优先级高。

5. 源码及参考

Josiah L. Carlson 《Reids实战》

黄健宏 《Redis设计与实现》

Guess you like

Origin www.cnblogs.com/zwwhnly/p/12295692.html