一、Redis 持久化
我们知道Redis的数据是全部存储在内存中的,如果机器突然GG,那么数据就会全部丢失,因此需要有持久化机制来保证数据不会一位宕机而丢失。Redis 为我们提供了两种持久化方案,一种是基于快照,另外一种是基于 AOF 日志。接下来就来了解一下这两种方案。
1. 操作系统与磁盘首先我们需要知道 Redis 数据库在持久化中扮演了什么样的角色,为此我们先来了解数据从 Redis 中到磁盘的这一过程:
客户端向数据库发起 write 指令(数据在客户端的内存中);
数据库收到 write 指令和对应的写数据(数据在服务端内存中);
数据库调用将数据写入磁盘的系统调用函数(数据在系统内核缓冲区);
操作系统将写入缓冲区中的数据写到磁盘控制器中(数据在磁盘缓冲区中);
磁盘控制器将磁盘缓冲区中的数据写入磁盘的物理介质中(数据真正写入磁盘中)。
上面只是简要介绍了一下过程,毕竟真实的缓存级别只会比这更多。不过我们可以从上面了解到,数据库在持久化的过程中主要应该去实现步骤3,也就是将原本在内存中的数据持久化到操作系统的内核缓冲区中。至于下面的两步,则是操作系统需要关心的事,数据库无能为力。数据库通常仅在必要的时候会去调用将数据从内存写入磁盘的系统调用。
2. 持久化方案对于上面我们所述的持久化过程,Redis 提供了以下几种不同的持久化方案:
利用 RDB 持久化在指定的时间间隔生成数据集的时间点快照(point-in-time );
利用 AOF 持久化将服务器收到的所有写操作命令记录下来,并在服务器重新启动的时候,利用这些命令来恢复数据集。AOF 的命令使用的是与 Redis 本身协议的命令一致,通过追加的方式将数据写入备份文件中,同时当备份文件过大时,Redis 也能对备份文件进行重压缩。
如果仅希望数据只在数据库运行时存在,那么还可以完全禁用掉持久化机制;
Redis还可以同时使用 AOF 持久化和 RDB 持久化。在这种情况下,当 AOF 重启时,会优先使用 AOF 文件去恢复原始数据。因为 AOF 中保存的数据通常比 RDB 中保存的数据更加完整。
接下来就重点讲解 RDB 持久化方案与 AOF 持久化方案之间的异同。
二、RDB 持久化RDB(Redis Database) 通过快照的形式将数据保存到磁盘中。所谓快照,可以理解为在某一时间点将数据集拍照并保存下来。Redis 通过这种方式可以在指定的时间间隔或者执行特定命令时将当前系统中的数据保存备份,以二进制的形式写入磁盘中,默认文件名为dump.rdb。
RDB 的触发有三种机制,执行save命令;执行bgsave命令;在redis.config中配置自动化。
1. save 触发Redis是单线程程序,这个线程要同时负责多个客户端套接字的并发读写操作和内存结构的逻辑读写。而save命令会阻塞当前的Redis服务器,在执行该命令期间,Redis无法处理其他的命令,直到整个RDB过程完成为止,用一张图描述以下:
当这条指令执行完毕,将RDB文件保存下来后,才能继续去响应请求。这种方式用于新机器上数据的备份还好,如果用在生产上,那么简直是灾难,数据量过于庞大,阻塞的时间点过长。这种方式并不可取。
2. bgsave 触发为了不阻塞线上的业务,那么Redis就必须一边持久化,一边响应客户端的请求。所以在执行bgsave时可以通过fork一个子进程,然后通过这个子进程来处理接下来所有的保存工作,父进程就可以继续响应请求而无需去关心I/O操作。
3. redis.config 配置上述两种方式都需要我们在客户端中去执行save或者bgsave命令,在生产情况下我们更多地需要是自动化的触发机制,那么Redis就提供了这种机制,我们可以在redus.config中对持久化进行配置:
################################ 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