Redis持久化策略(RDB&AOF)

持久化是将数据写入持久存储,例如固态磁盘(SSD)。本文主要基于Redis 4.0.11版本编写,Redis主要提供了RDB 和 AOF 以及 RDB和AOF混合模式 等几种持久化策略。截止本文编辑时间,Redis最新版本为7.2.4,对于4.0.11版本之后至最新版本中间的一些新特性或变化,本文会特殊说明。

RDB方式

RDB方式,将当前redis实例内存中的数据集快照写入磁盘。恢复时,直接将快照文件读到内存中。RDB有两种触发方式,自动触发和手动触发。

自动触发

在redis.conf中我们看到有个save配置,它定义了redis进行写磁盘的触发规则。

save #表示在seconds秒内进行了changes次修改就触发bgsave。

默认配置如下:

save 900 1 #每900秒内有1次修改就保存
save 300 10 #每300秒内有10次修改就保存
save 60 10000 #每60秒内有10000次修改就保存

如果是只使用redis缓存功能,不需要持久化。可以注释掉所有save来停用功能,也可以添加一个空串配置来实现:save "",还可以通过命令设置:redis-cli config set save "",注意:命令修改方式在重启后会失效

手动触发

手动触发的命令有两种,分别为save和bgsave

  • save会阻塞redis服务器,执行save期间,redis不能处理其他命令,直到rdb过程结束
  • bgsave会以异步的方式进行快照操作,期间可以继续响应客户端的请求。

其他配置

  • stop-writes-on-bgsave-error:默认配置为yes。当启用了rdb且最近一次后台保存数据失败,redis会停止接收处理请求。这会让用户注意到数据没有正确持久化到磁盘上,否则没有人会注意到这个灾难发生了。
  • rdbcompression:默认yes,表示保存到磁盘上的RDB快照会就行压缩处理,采用LZF算法。
  • rdbchecksum:默认yes,表示会对数据就行校验,采用CRC64算法,大约会增加10%的性能消耗
  • dbfilename:快照文件名,默认dump.rdb
  • dir:快照文件存放路径,这个配置项一定是个目录,而不能是文件名。

优点

  1. 压缩的RDB文件是一个非常紧凑的文件,非常适合做数据备份和恢复。
  2. rdb能最大化redis性能,因为主进程只需要fock一个子进程,快照操作完全由子进程处理。
  3. 由于是一个非常紧凑文件,故在数据恢复或者重启时可以直接被load到内存中,因此比AOF快很多。

劣势

  1. 无法做到实时持久化/秒级持久化,每次bgsave都要fock一个子进程,属于重量级操作,频繁执行也会影响性能。
  2. 由于是隔一段时间做一次备份,所以如果redis意外down调,就会丢失最后一次快照后的所有修改
  3. RDB二进制文件在版本演进的过程中,存在二进制文件格式兼容问题

工作流程

  1. 首先fork一个子进程
  2. 子进程开始备份数据到临时的rdb文件
  3. 当子进程备份完成,会用新生成的rdb文件替换原有的rdb文件

AOF方式

区别于RDB通过快照备份内存数据的方式,AOF是通过保存Redis所有执行的写命令来完成持久化的

appendonly yes

通过修改appendonly为yes,可开启AOF持久化功能。RDB和AOF可同时启用,如果启用了AOF,redis启动时会优先采用AOF方式加载数据。当写入的执行命令日志文件很大时,redis可以重写日志文件。(比如对先添加后删除的缓存key做合并处理,即不记录该key操作)。aof保存文件的目录和rdb文件在同一个位置,都是通过dir选项指定。

Reids >=7.0.0

从redis 7.0.0开始,redis使用了多部分aof机制,原始的单个aof文件被分成基本文件(最多一个)和增量文件(可能多个)。基本文件表示重写aof时呈现的数据的初始快照。增量文件包含最后一个基本AOF文件创建以来的增量更改。所有这些文件都放在一个单独的目录中,并由一个清单文件跟踪。

其他配置

  • appendfilename:aof文件名,默认是"appendonly.aof"
  • appendfsync:aof持久化策略的配置,默认everysec
    • no:不执行fsync,由操作系统保证数据同步到磁盘,速度最快,缺乏安全。Linux系统一般30秒刷一次数据,但这也取决于精确的内核调优。
    • always:每次写入都执行fsync,比较慢,但很安全
    • everysec:每秒执行一次fsync,可能会导致丢失这1s数据。通常选择 everysec ,兼顾安全性和效率。
  • no-appendfsync-on-rewrite:默认设置no。在同时执行bgrewriteaof和主进程写aof文件时,由于两者都会操作磁盘,且bgrewriteaof操作往往会涉及大量io操作,这样就会造成主进程写aof出现阻塞的情形,默认配置就是要忍受阻塞,虽然会影响性能,但是最安全,不会造成数据丢失。如果配置成yes,相当于appendfsync使用no策略,aof文件的写操作会放到缓冲区,由操作系统决定数据写入磁盘时机。这样在bgrewriteaof期间,就不会出现阻塞,但是redis挂掉了,就有可能造成30秒的数据丢失。
  • auto-aof-rewrite-percentage:默认100,表示aof文件大小增加100%时,就执行bgrewriteaof操作,首先要满足aof文件大小达到auto-aof-rewrite-min-size设置的值。
  • auto-aof-rewrite-min-size:默认64mb,表示aof最小达到64兆,才会触发bgrewriteaof操作。
  • aof-load-truncated:默认yes,在redis启动aof文件数据被载入内存时,aof文件可能在尾部是不完整的。这可能发生在redis正在运行但是系统宕机的时候,尤其是在挂载了没有配置data=ordered选项的ext4文件系统时(但是redis自己宕机或者异常终止不会造成尾部不完整现象)。如果设置yes,当截断的aof文件被载入时,redis服务开始发送一个日志通知用户事件。否则,服务会拒绝启动。当设置为no时,在重启服务前用户需要先用redis-check-aof工具来修复aof文件。如果发现aof文件在中间损坏,服务器仍然会退出并发出一个错误。
  • aof-use-rdb-preamble:默认no,当重写aof文件时,redis会在AOF中使用rdb前导,以更快的重写和恢复。当此选项配置成yes时,重写的AOF文件由两部分组成[rdb_file][aof_tail],相当RDB-AOF混合模式。当redis载入aof文件并识别到文件以REDIS开头时,会载入带前缀的rdb文件,然后载入aof尾。

恢复

重启redis后就会进行aof文件载入

异常修改可使用命令:redis-check-aof [--fix] ,--fix表示让redis自行修复,当aof文件在中间损坏时,不建议自行修复,因为redis会截断损坏位置到文件结尾的所有内容,这将导致大量数据丢失。注意:在最新的版本中,如果aof文件结尾被截断,redis重启会自动抛弃掉结尾不符合格式规范的数据。

如果aof文件不是在结尾被截断,而是在中间有字节序列损坏,情况就复杂了。redis在启动时会报错并终止。最好的办法是运行不带--fix选项的 redis-check-aof 命令进行初步修复。然后跳转到对应位置,看能不能手动修复aof文件,aof文件使用与redis协议相同的格式,所以处理起来比较简单。如果带--fix选项,让程序自行修复,可能导致损坏部位到文件末尾都被丢弃。如果损坏刚好发生在文件开始部分,这会导致丢失大量数据。

AOF重写

由于aof持久化是不断的将redis写命令写入到aof文件,随着redis运行,aof文件会越来越大,文件越大,占用的磁盘空间就越大,并且恢复时间就越长。为了解决这个问题,redis增加了重写机制,当aof文件大小超过设定的阈值时,redis就会启动重写,保留恢复数据的最小指令集。可以使用bgrewriteaof命令来启用重写。

优点

  1. aof不同的持久化策略可以可以满足不通的性能需求。默认每秒一次fsync仍然有比较好的性能。最多丢失1秒的写请求数据。
  2. aof文件是一个追加插入式的日志文件。在电源中断的情况下,也不会有损坏的问题。即使日志最后写了一半命令,使用redis-check-aof工具也能够轻松修复它。
  3. 当aof文件足够大时,redis能够自动的重写aof文件。并且该过程通过子进程来处理,不影响主进程继续处理新的修改。
  4. 由于aof文件由一个个容易理解且解析的命令组成。即时由于误操作执行了FLASHALL操作,只要在aof文件未执行重写之前,停服,通过移除aof文件最新的命令,再重启redis,也能保证数据不会丢失。

劣势

  1. 存储相同的数据aof文件通常要比rdb文件大很多
  2. 由于确切的fsync策略,aof会比rdb慢很多。一般每秒一次fsync的性能仍然很高,甚至在高负载的情况下无fsync拥有着和rdb相当的性能。但是rdb在巨大写负载的情况下,仍能够提供更多关于最大延迟的保证。
  3. 可能会出现比较罕见的在重新加载数据时不能完全复制相同数据集的错误。

工作流程

Redis<7.0

  1. 首先fork一个子进程
  2. 子进程开始写临时的新aof文件
  3. 主进程同时开始将新的修改保存在一块缓存中(期间修改仍然会写入旧的aof文件)
  4. 当子进程重写结束,会给主进程发送一个信号,主进程收到信息号并阻塞,子进程开始将缓存中的修改继续写入新的aof文件。
  5. 写入完毕后,会用新的aof文件替换旧的aof文件,然后开始将新的数据修改命令往新aof文件中写。

Redis>=7.0

  1. 首先fork一个子进程
  2. 子进程开始写临时新基本aof文件
  3. 主进程打开一个新的增量aof文件并写入更新。如果子进程重写失败,旧的基本文件和增量文件加上这个新的增量文件代表完整的数据集。
  4. 当子进程重写结束,会给主进程发送一个信号,并使用主进程新生成的增量文件和子进程生成的基本文件构建一个临时清单,并将其持久化。
  5. 最后redis对清单文件进行原子交换,以便AOF重写的结果生效。redis还会清理旧的基本文件和任何未使用的增量文件。

你可能感兴趣的:(Redis,redis,缓存)