redis提供了两种不同的持久化方法来将数据存储到硬盘里面。一种方法叫快照,它可以将存在于某一时刻的所有数据都写入硬盘里面。另一种方法叫只追加文件(AOF),它会在执行写命令时,将被执行的写命令复制到硬盘里面。这两种持久化方法既可以同时使用,又可以单独使用,在某些情况下甚至可以两种方法都不用,具体选择哪种持久化方法,需要根据用户的数据及应用来决定。
redis可以通过创建快照来获得在内存里面的数据在某个时间点上的副本。在创建快照之后,用户可以对快照进行备份,可以将快照复制到其他的服务器从而创建具有相同数据的服务器副本,还可以将快照留在原地以便重启服务器使用。
触发RDB持久化可以分为:手动触发和自动触发两种模式!
手动触发分别对应save命令和bgsave命令
除手动触发外,redis可以使用save命令配置redis内部的自动触发机制,如下:
快照的配置如下:
save 60 1000stop-srites-on-bgsave-error no rdbcompression on dbfilename dump.rdb
创建快照的几种方法:【虽然是save命令,但是触发的是bgsave操作】
在只使用快照持久化来保存数据时,一定要记住:如果系统真发生崩溃,用户将丢失最近一次生成快照之后的更改的所有数据。因此,快照持久化只适用于那些即使丢失一部分数据也不会造成问题的应用程序。
bgsave是主流的触发rdb持久化方式,执行流程如下:
运维提示:
1:rdb文件的位置可以在线动态修改,可以使用config set dir指定rdb文件的位置,使用config set dbfilename执行文件名。
2:redis默认采用LZF算法对生成的rdb文件做压缩处理,压缩后的文件远远小于内存大小,默认开启,可以使用config set rdbcompression动态修改。虽然压缩rdb会消耗cpu,但可大幅度降低文件体积,方便保存到硬盘或通过网络发送给从节点,因此线上建议开启。
RDB的优缺点:
RDB是一个紧凑压缩的二进制文件,代表redis在某个时间点上的数据快照。非常适用于备份,全量恢复等场景。redis加载rdb恢复数据远远快于AOF方式。
RDB的缺点:
RDB方式数据没办法做到实时持久化/秒级持久化。因为bgsave每次运行都要执行fork操作常见子进程,属于重量级操作,频繁执行成本过高。RDB文件使用特定的二进制格式保存,redis版本演进过程中有多个格式的RDB版本,存在老版本redis服务无法兼容新版本rdb格式的问题。
简单来说,AOF持久化会将被执行的写命令写到AOF文件的末尾,以此来记录数据发生的变化。因此,redis只要从头到尾重新执行一次AOF文件包含的所有写命令,就可以恢复AOF文件所记录的数据集。AOF持久化可以通过设置如下选项来打开。AOF的主要作用是解决了数据持久化的实时性,目前已经是redis持久化的主流方式。
appendonly no #是否开启aof持久化 appendfsync everysec no-appendfsync-on-rewrite no auto-aof-rewrite-percentage 100auto-aof-rewrite-min-size 64mb dir ./ #这个参数决定来持久化文件保存的位置
appendfsync参数有三个选项:
always: 每个redis写命令都要同步写入硬盘,这样会严重降低redis的速度。 everysec: 每秒执行一次同步,显式地将多个写命令同步到硬盘。 no : 让操作系统来决定应该何时进行同步。
aof处理流程如下:
*1:aof命令写入的内容直接是文本协议格式;文本协议有很好的兼容性;开启aof后,所有写入命令都包含追加操作,直接采用协议格式,避免了二次处理开销。文本协议具有可读性,方便直接修改和处理。
*2:aof为什么吧命令追加到aof_buf中?redis使用单线程相应命令,如果每次写aof文件命令都直接追加到硬盘,那么性能完全取决于当前硬盘负载。先写入aof_buf中,还有另一个好处,redis可以提供多种缓冲区同步硬盘的策略,在性能和安全性方面做出平衡。
aof_buf同步到磁盘的策略,可以使用appendfsync参数来控制!
*3:重新机制
随着命令不断写入AOF,文件会越来越大,为了解决这个问题,redis引入了aof重写机制压缩文件体积。aof文件重写使redis进程内的数据转化为写命令同步到新aof文件的过程。
重写后aof文件为什么可以表小?
aof重写降低了文件占用空间,除此之外,另一个目的:更小的aof文件可以更快第被redis加载。
aof重写过程可以手动触发或自动触发:
aof持久化可以通过设置auto-aof-rewrite-percentage选项和auto-aof-rewrite-min-size选项来自动执行bgrewriteaof。默认的配置如下:
auto-aof-rewrite-percentage -aof-rewrite-min-size 64mb #那么当aof文件的体积大于64MB,并且aof文件的体积比上一次重写之后的体积大至少一倍(100%)的时候,redis将执行bgrewriteaof命令。如果aof重写执行得过于频繁的话,用户可以考虑将auto-aof-rewrite-percentage选项的值设置为100以上, #这种做法可以让redis在aof文件的体积变得更大之后才执行重写操作,不过也会让redis在启动时还原数据集所需的时间变得更长。 自动触发机制:aof_current_size>auto-aof-rewrite-min-size&&(aof_current_size减去aof_base_zise)/aof_base_size>=auto-aof-rewrite-percentag 其中:aof_current_size和aof_base_size可以在info命令统计信息中查看
1:执行aof重写请求,如果当前进程正在执行aof重写,请求不执行并且返回如下响应:
ERR Background append only file rewriting already in progress
如果当前进程正在执行bgsave操作,重写命令延迟到bgsave完成之后再执行,返回如下响应:
Background append only file rewriting scheduled
2:父进程执行fork创建子进程,开销等同于bgsave过程。
3.1: 主进程fork操作完成后,继续响应其他命令。所有修改命令依然写入aof缓冲区并根据appendfsync策略同步到硬盘,保证原有aof机制正确。
3.2:由于fork操作运用写时复制技术,子进程只能共享fork操作时的内存数据。由于父进程依然响应命令,redis使用‘AOF重写缓冲’保存这部分数据,防止新AOF文件生成期间丢失这部分数据。
4:子进程根据内存快照,按照命令合并规则写入到新的AOF文件。每次批量写入硬盘数据量由配置aof-rewrite-incremental-fsync控制,默认为32MB,防止单次刷盘过多造成硬盘阻塞。
5:新aof文件写入完成后,子进程发送信号给父进程,父进程更新统计信息。父进程把aof重写缓冲区的数据写入到新的aof文件,使用新aof文件替换老文件,完成aof重写。
redis重启加载流程:
1:aof持久化开启并存在aof文件时,优先加载aof文件。
2:aof关闭或者aof文件不存在时,加载rdb文件。
3:加载aof/rdb文件成功后,redis启动成功。
4:aof/redis文件存在错误时,redis启动失败并打印错误信息。
无论是快照持久化还是aof持久化,都提供了在遇到系统故障时进行数据恢复的工具。redis提供来两个命令行程序redis-check-aof和redis-check-dump,它们可以在系统故障发生之后,检查aof文件和快照文件的状态,并在有需要的情况下对文件进行修复。
[root@test2 redis]# redis-check-aof Usage: redis-check-aof [--fix][root@test2 redis]# redis-check-rdb Usage: redis-check-rdb[root@test2 redis]#
如果用户在运行redis-check-aof程序时给定了--fix参数,那么程序将对aof文件进行修复。程序修复aof文件的方法非常简单:它会扫描给定的aof文件,寻找不正确或者不完整的命令,当发现第一个出错命令的时候,程序会删除出错的命令以及位于出错命令之后的所有命令,只保留那些位于出错命令之前的正确命令。在大多数情况下,被删除的都是aof文件末尾的不完整的写命令。