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