目录
一、RDB
1、什么是RDB
RDB(Redis DataBase)指的是在指定时间间隔内对数据集做快照,然后IO到磁盘上进行保存(dump.rdb),实现冷备,在Redis重启时将快照文件从磁盘读取到内存。
2、RDB原理
当RDB持久化被触发(触发分为手动触发与自动触发)时,主进程会fork一个子进程来进行持久化,会先将数据集写到一 个临时文件中,待数据集快照完毕之后,通过rename操作用新文件覆盖掉旧的dump.rdb。在整个RDB持久化过程中主进程不会被阻塞,这就保证主进程的极高性能,不影响主进程响应其他命令。Fork的作用是复制一个与当前主进程一样的子进程,新进程的所有数据数值与主进程一致,但是他是一个全新的进程并且是主进程的子进程。主进程在fork子进程的过程中会被阻塞,不能继续响应其他操作。
注:这里注意的是 fork 操作会阻塞,导致Redis读写性能下降。我们可以控制单个Redis实例的最大内存,来尽可能降低Redis在fork时的事件消耗。以及上面提到的自动触发的频率减少fork次数,或者使用手动触发,根据自己的机制来完 成持久化。
3、如何触发RDB
1>、手动触发:save、bgsave命令:
save:该命令会阻塞当前redis服务器,直到持久化结束,不提倡;
bgsave:该命令会fork出子进程,由子进程负责进行持久化,持久化过程不会阻塞主进程,但是fork子进程的时候会阻塞主 进程。
2>、自动触发
①、主从复制时从节点发送psync命令进行full resync时,触发主节点的pgsave命令 ,主节点发送rdb文件给从节点。
②、根据配置文件中的save m n 规则自动触发:
save 900 1:在900秒(15分钟)之后,如果至少有1个key发生变化,则dump内存快照。
save 60 10000:在60秒(1分钟)之后,如果至少有10000个key发生变化,则dump内存快照。
③、执行shut down时,如果没有开启AOF也会触发。
4、RDB优势
相较与AOF,如果数据集很大,RDB在数据恢复时效率更高。如果对数据恢复的完整性要求不高可以使用RDB。
5、RDB劣势
1>、若当前的进程的数据量庞大,那么 fork 之后数据量*2,此时就会造成服务器压力大,运行性能降低;
2>、隔一段时间做一次数据备份,如果redis意外down掉,就会造成最后一次快照后所有的修改丢失。
二、AOF
1、什么是AOF
AOF(Appendonly File)以日志的形式来记录所有的写操作,将redis执行过的所有写指令(不包括读指令)都追加到文件最后(只能追加文件不能修改文件)。Redis启动之初会读取appendonly.aof文件中的指令重新执行构建数据,从而达到恢复数据的目的。
2、AOF的持久化配置
1>、每次修改同步 appendfsync always 同步持久化,每次发生数据变更都会立即写到磁盘,性能较差但是数据完整性比较 好;
2>、每秒同步 appendfsync everysec 异步持久化,每秒记录,如果一秒内宕机,会丢失一秒的数据;
3>、不同步 appendfsync no 从不同步。
3、AOF的原理
AOF的流程主要分为两部分:命令的追加写入(写入的策略根据上述AOF持久化配置)、AOF重写rewrite:
1>、命令追加写入(以每秒写入为例):
写入的命令=》追加到AOF_BUF=》每隔一秒异步读取AOF_BUF中的所有指令同步追加到appendonly.aof文件。
2>、AOF重写rewrite
AOF重写是为了压缩appendonly.aof文件的大小,因为随着时间推移指令不停的追加到appendonly.aof,导致文件越来越大,为避免出现这种情况增加了重写机制。当aof文件大小超过某个阈值时会自动触发重写机制,生成新的只保留了能恢复数据集的最小指令的文件,来覆盖旧文件。当然也可以通过手动触发该机制:使用bgrewriteaof指令,异步执行一个AOF文件重写操作。
AOF重写机制是通过fork出一个子进程,遍历新进程的内存中的数据,每条记录都有一个set语句,会把该语句写到临时文件中,遍历完成后,通过rename覆盖旧文件完成重写机制(有点类似快照的过程)。
3>、重写自动触发时机:Redis会记录上次重写时的AOF大小,默认配置是当AOF文件大小是上次rewrite后大小的一倍且文件大于64M时触发。
4、AOF优势
1>、AOF比RDB的数据完整性更高;
2>、AOF文件是一个只进行追加操作的日志文件(append only log),因此对 AOF文件的写入不需要进行 seek ,即使日志因为某些原因而包含了未写入完整的命令(比如写入时磁盘已满,写入中途停机,等等),redis-check-aof 工具也可以轻易地修复这种问题;
3>、Redis 可以在 AOF 文件体积变得过大时,自动地在后台对 AOF 进行重写:重写后的新 AOF 文件包含了恢复当前数据集所需的最小命令集合。 整个重写操作是绝对安全的,因为 Redis 在创建新AOF文件的过程中,会继续将命令追加到现有的AOF文件里面,即使重写过程中发生停机,现有的 AOF 文件也不会丢失。 而一旦新 AOF 文件创建完毕,Redis 就会从旧AOF 文件切换到新 AOF 文件,并开始对新 AOF 文件进行追加操作;
4>、AOF 文件有序地保存了对数据库执行的所有写入操作,这些写入操作以 Redis 协议的格式保存,因此AOF文件的内容非常容易被人读懂,对文件进行分析(parse)也很轻松。导出(export) AOF文件也非常简单:举个例子,如果你不小心执行了 FLUSHALL 命令,但只要AOF文件未被重写,那么只要停止服务器,移除AOF文件末尾的 FLUSHALL 命令,并重启Redis,就可以将数据集恢复到 FLUSHALL 执行之前的状态。
5、AOF劣势
1>、相较于RDB,appendonly.aof文件体积比dump.rdb更大,恢复速度更慢;
2>、根据所使用的 appendfsync策略,AOF的速度可能会慢于RDB 。 在一般情况下, 每秒 appendfsync的性能依然非常高,而关闭 appendfsync可以让AOF的速度和 RDB 一样快, 即使在高负荷之下也是如此。 不过在处理巨大的写入载入时,RDB 可以提供更有保证的最大延迟时间(latency);
3>、AOF在过去曾经发生过这样的 bug : 因为个别命令的原因,导致 AOF 文件在重新载入时,无法将数据集恢复成保存时的原样。(举个例子,阻塞命令 BRPOPLPUSH 就曾经引起过这样的bug)测试套件里为这种情况添加了 测试:它们会自动生成随机的、复杂的数据集,并通过重新载入这些数据来确保一切正常。虽然这种bug在AOF文件中并不常见,但是对比来说,RDB几乎是不可能出现这种bug的。
6、AOF的rewrite流程
对于上图有四个关键点补充一下:
1>、在重写期间,由于主进程依然在响应命令,为了保证最终备份的完整性;因此它依然会写入旧的AOF file中,如果 重写失败,能够保证数据不丢失;
2>、为了把重写期间响应的写入信息也写入到新的文件中,因此也会为子进程保留一个buf,防止新写的file丢失数据;
3>、重写是直接把当前内存的数据生成对应命令,并不需要读取老的AOF文件进行分析、命令合并;
4>、AOF文件直接采用的文本协议,主要是兼容性好、追加方便、可读性高可人为修改修复。
注意:不管是RDB还是AOF都是先写入一个临时文件,然后通过 rename 完成文件的替换工作。