Redis的持久化机制

455 阅读6分钟

最近在看《Redis In Action》这本书,买了好久了,开始因为书里的代码是python的就先搁置了,现在又拿起来读了读,发现这书还挺不错的。Redis学习以及项目中使用已经用了很久了,也该整一个Redis专栏来总结总结了,那就先从重要而开发人员又容易忽视但面试却又经常被问到的Redis的持久化开始聊吧

1、从官方文档说起

Redis的管方文档是十分详细的,关于 Redis的持久化 ,文当中详细的介绍了两种持久化方式,即:RDB (Redis Database)和AOF(Append Only File),包括了RDB,AOF的定义,以及两者的优缺点,和工作方式,我们如何选择持久化方式等。官方文档就是最好的学习Redis的资料,在此,也是对官方资料的总结而已。

2、工作原理

1、RDB

是什么

RDB是会在指定的时间将内存中的数据集写入到磁盘的快照(Snapshot)文件中,恢复的时候也就是将快照文件直接读入到内存中。

怎么工作的

Redis会fork出一个子进程,这个子进程会将内存数据写入到一个临时的文件当中,当子进程备份完毕后,就会将这个临时文件替换为新的Snapshot文件。整个过程中,主进程是不参与IO操作的,可以继续处理客户端的其它请求(整个工作原流程如下图)。 RDB持久化过程

RDB的同步策略

格式:save 秒数 写操作的次数

含义:在指定的秒钟内,发生了指定次数的写操作就会触发RDB文件同步

默认配置: 1分钟内改了1万次,或5分钟内改了100次,或15分钟内改了1次

	save 3600 1
	save 300 100
	save 60 10000

禁用方式:不设置save指令,或者给save传入空字符串

	save ""

2、AOF

是什么

Redis会将每次的写操作的命令追加到日志文件中,当服务器重启是,服务器会执行日志中的命令来重构数据。

怎么工作的

首先,Redis会将所有的写命令写入到AOF缓冲区中,然后根据设置的持久化策略进行将缓冲区刷到硬盘上的日志文件中;当AOF文件的大小超过设置的重写策略或者手动进行重写时,会对AOF文件rewrite重写,压缩AOF文件容量(整个工作流程如下)

AOF工作流程

AOF的同步策略:

文件同步 在向磁盘写入文件时,至少会发生3件事。当调用file.write()方法对文件进行写入时,写入的内容首先会被存储到缓冲区,然后操作系统会在将来的某个时候将缓冲区存储的内容写入磁盘,而数据只有在被写入磁盘之后,才算是正在的保存到了磁盘里面。用户可以通过调用file.flush()方法来请求操作系统尽快地将缓冲区存储的数据写入磁盘里,但具体何时执行写入操作仍然由操作系统决定。除此之外,用户还可以命令操作系统将文件同步(sync)到磁盘,同步操作会一直阻塞直到指定的文件被写入硬盘位置,当同步操作执行完毕之后即使操作系统出现故障也不会对被同步的文件造成任何影响。 文件同步磁盘的过程

  1. appendfsync always : 每执行一个命令,就追加一次AOF磁盘文件,虽然这样能最大限度的减少数据丢失,但是性能很差
  2. appendfsync everysec : 每秒钟同步到磁盘一次,这种情况下性能可以与RDB相媲美,而且最多丢失最后一秒钟的数据,这也是官方 默认和推荐的AOF持久化策略
  3. appendfsync no : 不进行设置,只把数据交给操作系统,让操作系统根据自己的配置进行刷盘

AOF文件重写

1、重写的流程
  1. bgrewriteaof触发重写,判断是否当前有bgsave或bgrewriteaof在运行,如果有,则等待该命令结束后再继续执行
  2. 主进程fork出子进程执行重写操作,保证主进程不会阻塞。
  3. 子进程遍历redis内存中数据到临时文件,客户端的写请求同时写入aof_buf缓冲区和aof_rewrite_buf重写缓冲区保证原AOF文件完整以及新AOF文件生成期间的新的数据修改动作不会丢失。
  4. 1).子进程写完新的AOF文件后,向主进程发信号,父进程更新统计信息。2).主进程把aof_rewrite_buf中的数据写入到新的AOF文件。
  5. 使用新的AOF文件覆盖旧的AOF文件,完成AOF重写。 (流程如下) AOF文件重写的过程
2、重写的配置

Redis的2.2版本及之前,需要我们手动的一次一次的来执行BGREWRITEAOF命令来完成AOF文件重写 而在Redis2.4版本开始,我们可以在配置文件配置好,就可以自动的进行BGREWRITRAOF,例如

	auto-aof-rewrite-min-size 64mb
	auto-aof-rewrite-percentage 100

该例子中这么配置的含义是:当AOF文件的体积大于64MB,并且AOF文件的体积比上一次重写之后的体积大了至少一倍(100%)的时候,Redis将执行BGREWRITEAOF

3、Redis的两种持久化机制的优缺点

1、RDB

优点

  1. RDB的备份进程是在后台进行的,不影响主进程对命令的操作.主进程不参与IO操作
  2. 当Redis服务重启的时候,RDB方式是比AOF方式恢复数据要快的

缺点

  1. 在Redis突然宕机的时候,会大概率丢失最后一次的快照数据
  2. 在Fork的时候,内存中的数据被克隆了一份,大致2倍的膨胀性需要考虑
  3. RDB方式备份数据的时候,需要主进程fork()出一个子进程,当需要备份的数据集很大的时候,就会影响到主进程,会是主进程对外无法提供正常的工作

2、AOF

优点

  1. AOF能够最大化的进行持久化,在设置每秒追加aof文件的情况下,性能依旧很高,所以最多只会丢失最后一秒的数据
  2. AOF日志是追加日志,所以不会出现寻道问题,以及文件损坏问题,即使在最后一条指令写入一半的时候宕机,也可以通过Redis提供的redis-check-aof工具来进行文档修复
  3. 当AOF文件很大的时候,会有后台进程来重写AOF文件,从而减小文件大小

缺点

  1. 在相同数据集下,AOF文件的大小通常要比RDB文件大
  2. 在不同的写入文件的策略下,AOF可能会比RDB慢

4、我们该怎么选择呢?

在官方文档中,Redis大叔是推荐我们两种备份方式同时使用的,可以取长补短,利用AOF的备份数据完全的优点,以及RDB能够快速重启服务器的优点,才能更好的实现Redis持久化。 (官方文档解释如下) 官方建议设置持久化