Redis 进阶 -- 持久化(RDB持久化AOF持久化RDB-AOF混合持久化无持久化)
Posted CodeJiao
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Redis 进阶 -- 持久化(RDB持久化AOF持久化RDB-AOF混合持久化无持久化)相关的知识,希望对你有一定的参考价值。
文章目录
持久化
Redis与传统数据库的一个主要区别在于,Redis把所有数据都存储在内存中,而传统数据库通常只会把数据的索引存储在内存中,并将实际的数据存储在硬盘中。
虽然Redis的数据存储方式使得用户可以以极快的速度读写服务器中的数据,但由于内存属于易失存储器(volatile storage),它记录的所有数据在系统断电之后就会丢失,这对于想把Redis用作数据库而不仅仅是缓存的用户来说是不愿意看到的。
为了满足不同的持久化需求,Redis提供了RDB持久化、AOF持久化和RDB-AOF混合持久化等多种持久化方式以供用户选择。如果用户有需要,也可以完全关闭持久化功能,让服务器处于无持久化状态。
1. RDB持久化
RDB持久化是Redis默认使用的持久化功能,该功能可以创建出一个经过压缩的二进制文件,其中包含了服务器在各个数据库中存储的键值对数据等信息。RDB持久化产生的文件都以.rdb后缀结尾,其中rdb代表Redis DataBase(Redis数据库)。
Redis提供了多种创建RDB文件的方法,用户既可以使用SAVE命令或者BGSAVE命令手动创建RDB文件,也可以通过设置save配置选项让服务器在满足指定条件时自动执行BGSAVE命令。
1.1 SAVE:阻塞服务器并创建RDB文件
用户可以通过执行SAVE命令,要求Redis服务器以同步方式创建出一个记录了服务器当前所有数据库数据的RDB文件。SAVE命令是一个无参数命令,它在创建RDB文件成功时将返回OK作为结果。
接收到SAVE命令的Redis服务器将遍历数据库包含的所有数据库,并将各个数据库包含的键值对全部记录到RDB文件中。在SAVE命令执行期间,Redis服务器将阻塞,直到RDB文件创建完毕为止。如果Redis服务器在执行SAVE命令时已经拥有了相应的RDB文件,那么服务器将使用新创建的RDB文件代替已有的RDB文件,这个过程如下图所示。
语法:
示例:
说明:
复杂度:O(N),其中N为Redis服务器所有数据库包含的键值对总数量。
1.2 BGSAVE:以非阻塞方式创建RDB文件
因为SAVE命令在执行时会阻塞整个服务器,所以用户在使用该命令创建RDB文件期间将无法为其他客户端提供服务。为了解决这个问题,Redis提供了SAVE命令的异步版本BGSAVE命令:这个命令与SAVE命令一样都是无参数命令,它与SAVE命令的不同之处在于,BGSAVE不会直接使用Redis服务器进程创建RDB文件,而是使用子进程创建RDB文件。
当Redis服务器接收到用户发送的BGSAVE命令时,将执行以下操作:
- 创建一个子进程。
- 子进程执行SAVE命令,创建新的RDB文件。
- RDB文件创建完毕之后,子进程退出并通知Redis服务器进程(父进程)新RDB文件已经完成。
- Redis服务器进程使用新RDB文件替换已有的RDB文件。
下图展示了这一执行过程:
因为BGSAVE命令创建RDB文件的操作是由子进程以异步方式执行的,所以当用户在客户端执行这个命令时,服务器将立即向客户端返回OK,然后才会在后台开始具体的RDB文件创建操作:
因为BGSAVE命令是以异步方式执行的,所以Redis服务器在BGSAVE命令执行期间仍然可以继续处理其他客户端发送的命令请求。不过需要注意的是,虽然BGSAVE命令不会像SAVE命令那样一直阻塞Redis服务器,但由于执行BGSAVE命令需要创建子进程,所以父进程占用的内存数量越大,创建子进程这一操作耗费的时间也会越长,因此Redis服务器在执行BGSAVE命令时,仍然可能会由于创建子进程而被短暂地阻塞。
说明:
复杂度:O(N),其中N为Redis服务器所有数据库包含的键值对总数量。
1.3 通过配置选项自动创建RDB文件
用户除了可以使用SAVE命令和BGSAVE命令手动创建RDB文件之外,还可以通过设置save选项,让Redis服务器在满足指定条件时自动执行BGSAVE命令。
配置文件位置:redis安装目录/redis.conf
save选项接受seconds和changes两个参数,前者用于指定触发持久化操作所需的时长,而后者则用于指定触发持久化操作所需的修改次数。简单来说,如果服务器在seconds秒之内,对其包含的各个数据库总共执行了至少changes次修改,那么服务器将自动执行一次BGSAVE命令。
示例:
比如,如果我们向服务器提供以下选项:
save 60 10000
那么当“服务器在60s秒之内至少执行了10000次修改”这一条件被满足时,服务器就会自动执行一次BGSAVE命令。
同时使用多个save选项:
Redis允许用户同时向服务器提供多个save选项,当给定选项中的任意一个条件被满足时,服务器就会执行一次BGSAVE。
比如,如果我们向服务器提供以下选项:
save 6000 1
save 600 100
save 60 10000
那么当以下任意一个条件被满足时,服务器就会执行一次BGSAVE命令:
- 在6000s(100min)之内,服务器对数据库执行了至少1次修改。
- 在600s(10min)之内,服务器对数据库执行了至少100次修改。
- 在60s(1min)之内,服务器对数据库执行了至少10000次修改。
注意,为了避免由于同时使用多个触发条件而导致服务器过于频繁地执行BGSAVE命令,Redis服务器在每次成功创建RDB文件之后,负责自动触发BGSAVE命令的时间计数器以及修改次数计数器都会被清零并重新开始计数:无论这个RDB文件是由自动触发的BGSAVE命令创建的,还是由用户执行的SAVE命令或BGSAVE命令创建的,都是如此。
.4 SAVE命令和BGSAVE命令的选择
因为SAVE命令在创建RDB文件期间会阻塞Redis服务器,所以如果我们需要在创建RDB文件的同时让Redis服务器继续为其他客户端服务,那么就只能使用BGSAVE命令来创建RDB文件。
因为SAVE命令无须创建子进程,它不会因为创建子进程而消耗额外的内存,所以在维护离线的Redis服务器时,使用SAVE命令能够比使用BGSAVE命令更快地完成创建RDB文件的工作。
1.5 RDB文件结构
RDB文件的总体结构,整个文件共分为7个部分:
-
RDB文件标识符:文件最开头的部分为RDB文件标识符,这个标识符的内容为"REDIS"这5个字符。Redis服务器在尝试载入RDB文件的时候,可以通过这个标识符快速地判断该文件是否为真正的RDB文件。
-
版本号:跟在RDB文件标识符之后的是RDB文件的版本号,这个版本号是一个字符串格式的数字,长度为4个字符。目前最新的RDB文件版本为第9版,因此RDB文件的版本号将为字符串"0009"。不同版本的RDB文件在结构上都会有一些不同,总的来说,新版RDB文件都会在旧版RDB文件的基础上添加更多信息,因此RDB文件的版本越新,RDB文件的结构就越复杂。关于RDB文件,需要说明的另外一点是新版Redis服务器总是能够向下兼容旧版Redis服务器生成的RDB文件。
-
设备附加信息:RDB文件的设备附加信息部分记录了生成RDB文件的Redis服务器及其所在平台的信息,比如服务器的版本号、宿主机器的架构、创建RDB文件时的时间戳、服务器占用的内存数量等。
-
数据库数据:RDB文件的数据库数据部分记录了Redis服务器存储的0个或任意多个数据库的数据,当这个部分包含多数个数据库的数据时,各个数据库的数据将按照数据库号码从小到大进行排列,比如,0号数据库的数据将排在最前面,紧接着是1号数据库的数据,然后是2号数据库的数据,以此类推,下图展示了这一排列顺序。
-
Lua脚本缓存:如果Redis服务器启用了复制功能,那么服务器将在RDB文件的Lua脚本缓存部分保存所有已被缓存的Lua脚本。这样一来,从服务器在载入RDB文件完成数据同步之后,就可以继续执行主服务器发来的EVALSHA命令了。
-
EOF:RDB文件的EOF部分用于标识RDB正文内容的末尾,它的实际值为二进制值0xFF。当Redis服务器读取到EOF的时候,它知道RDB文件的正文部分已经全部读取完毕了。
-
CRC64校验和:RDB文件的末尾是一个以无符号64位整数表示的CRC64校验和,比如5097628732947693614。Redis服务器在读入RDB文件时会通过这个校验和来快速地检查RDB文件是否有出错或者损坏的情况出现。
数据库信息结构:
前面提到过,RDB文件的数据库数据部分包含了任意多个数据库的数据,其中每个数据库都由下图所示的4个部分组成。
首先,第一部分以数字形式记录了数据库的号码,比如0。Redis服务器在读入RDB文件数据时,会根据这个号码切换至相应的数据库,从而确保键值对会被载入正确的数据库中。
在之后的两个部分,RDB文件会使用两个数字,分别记录数据库包含的键值对总数量以及数据库中带有过期时间的键值对数量。Redis服务器将根据这两个数字,以尽可能优化的方式创建数据库的内部数据结构。
在最后一个部分,RDB文件将以无序方式记录数据库包含的所有键值对。具体来说,数据库中的每个键值对都会被划分为最多5个部分,如图所示。
每个键值对开头的第一部分记录的是可能存在的过期时间,这是一个毫秒级精度的UNIX时间戳。
之后的LRU信息或者LFU信息分别用于实现可选的LRU算法或者LFU算法,并且因为Redis只能选择一种键淘汰算法,所以这两项信息将不会同时出现,最多只会出现其中一种。
至于最后三个部分则分别记录了键值对的类型(比如字符串、列表、散列等)以及键和值。
1.6 载入RDB文件
首先,当Redis服务器启动时,它会在工作目录中查找是否有RDB文件出现,如果有就打开它,然后读取文件的内容并执行以下载入操作:
- 检查文件开头的标识符是否为"REDIS",如果是则继续执行后续的载入操作,不是则抛出错误并终止载入操作。
- 检查文件的RDB版本号,以此来判断当前Redis服务器能否读取这一版本的RDB文件。
- 根据文件中记录的设备附加信息,执行相应的操作和设置。
- 检查文件的数据库数据部分是否为空,如果不为空就执行以下子操作:
- 根据文件记录的数据库号码,切换至正确的数据库。
- 根据文件记录的键值对总数量以及带有过期时间的键值对数量,设置数据库底层数据结构。
- 一个接一个地载入文件记录的所有键值对数据,并在数据库中重建这些键值对。
- 如果服务器启用了复制功能,那么将之前缓存的Lua脚本重新载入缓存中。
- 遇到EOF标识,确认RDB正文已经全部读取完毕。
- 载入RDB文件末尾记录的CRC64校验和,把它与载入数据期间计算出的CRC64校验和进行对比,以此来判断被载入的数据是否完好无损。
- RDB文件载入完毕,服务器开始接受客户端请求。
下图展示了这一数据载入流程。
1.7 数据丢失
RDB文件记录的是服务器在开始创建文件的那一刻,服务器中包含的所有键值对数据,这种数据持久化方式通常被称为时间点快照(point-in-time snapshot)。时间点快照持久化的一个特点是,系统在停机时将丢失最后一次成功实施持久化之后的所有数据。对于一个只使用RDB持久化的Redis服务器来说,服务器停机时丢失的数据量将取决于最后一次成功执行的RDB持久化操作,以及该操作开始执行的时间。
1.8 RDB持久化的缺陷
总的来说,无论用户使用的是SAVE命令还是BGSAVE命令,停机时服务器丢失的数据量将取决于创建RDB文件的时间间隔:间隔越长,停机时丢失的数据也就越多。
然而矛盾之处在于,RDB持久化是一种全量持久化操作,它在创建RDB文件时需要存储整个服务器包含的所有数据,并因此消耗大量计算资源和内存资源,所以用户是不太可能通过增大RDB文件的生成频率来保证数据安全的。
举个例子,虽然从技术上来说,用户可以在每次执行写命令之后都执行一次SAVE命令,以此来保证数据处于绝对安全的状态,但这样一来Redis服务器的性能将下降至无法正常使用的水平。相反,用户如果想要保证服务器的性能处于合理水平,就不能过于频繁地创建RDB文件,这样一来,也就不可避免地会出现因为停机而丢失大量数据的情况。
从RDB持久化的特征来看,它更像是一种数据备份手段而非一种普通的数据持久化手段。为了解决RDB持久化在停机时可能会丢失大量数据这一问题,并提供一种真正符合用户预期的持久化功能,Redis推出了AOF持久化模式。
2. AOF持久化
与全量式的RDB持久化功能不同,AOF提供的是增量式的持久化功能,这种持久化的核心原理在于:服务器每次执行完写命令之后,都会以协议文本的方式将被执行的命令追加到AOF文件的末尾。这样一来,服务器在停机之后,只要重新执行AOF文件中保存的Redis命令,就可以将数据库恢复至停机之前的状态。
2.1 打开AOF持久化功能
用户可以通过服务器的appendonly选项来决定是否打开AOF持久化功能:
如果用户想要开启AOF持久化功能,那么只需要将这个值设置为yes即可:
反之,如果用户想要关闭AOF持久化功能,那么只需要将这个值设置为no即可。
配置文件位置:redis安装目录/redis.conf
当AOF持久化功能处于打开状态时,Redis服务器在默认情况下将创建一个名为appendonly. aof的文件作为AOF文件。
2.2 设置AOF文件的冲洗频率
为了提高程序的写入性能,现代化的操作系统通常会把针对硬盘的多次写操作优化为一次写操作。具体的做法是,当程序调用write系统调用对文件进行写入时,系统并不会直接把数据写入硬盘,而是会先将数据写入位于内存的缓冲区中,等到指定的时限到达或者满足某些写入条件时,系统才会执行flush系统调用,将缓冲区中的数据冲洗至硬盘。
这种优化机制虽然提高了程序的性能,但是也给程序的写入操作带来了不确定性,特别是对于AOF这样的持久化功能来说,AOF文件的冲洗机制将直接影响AOF持久化的安全性。为了消除上述机制带来的不确定性,Redis向用户提供了appendfsync选项,以此来控制系统冲洗AOF文件的频率:
appendfsync选项拥有always、everysec和no 3个值可选,它们代表的意义分别为:
- always——每执行一个写命令,就对AOF文件执行一次冲洗操作。
- everysec——每隔1s,就对AOF文件执行一次冲洗操作。
- no——不主动对AOF文件执行冲洗操作,由操作系统决定何时对AOF进行冲洗。
这3种不同的冲洗策略不仅会直接影响服务器在停机时丢失的数据量,还会影响服务器在运行时的性能:
- 在使用always值的情况下,服务器在停机时最多只会丢失一个命令的数据,但使用这种冲洗方式将使Redis服务器的性能降低至传统关系数据库的水平。
- 在使用everysec值的情况下,服务器在停机时最多只会丢失1s之内产生的命令数据,这是一种兼顾性能和安全性的折中方案。
- 在使用no值的情况下,服务器在停机时将丢失系统最后一次冲洗AOF文件之后产生的所有命令数据,至于数据量的具体大小则取决于系统冲洗AOF文件的频率。
因为no策略给可能丢失的数据量带来了不确定性,而always策略对于安全性的追求又牺牲了服务器的性能,所以Redis使用everysec作为appendfsync选项的默认值。除非有明确的需求,否则用户不应该随意修改appendfsync选项的值。
配置文件位置:redis安装目录/redis.conf
2.3 AOF重写
随着服务器不断运行,被执行的命令将变得越来越多,而负责记录这些命令的AOF文件也会变得越来越大。与此同时,如果服务器曾经对相同的键执行过多次修改操作,那么AOF文件中还会出现多个冗余命令。
冗余命令的存在不仅增加了AOF文件的体积,并且因为Redis服务器在停机之后需要通过重新执行AOF文件中保存的命令来恢复数据,所以AOF文件中的冗余命令越多,恢复数据时耗费的时间也会越多。为了减少冗余命令,并提供数据恢复操作的执行速度,Redis提供了AOF重写功能,该功能能够生成一个全新的AOF文件,并且文件中只包含恢复当前数据库所需的尽可能少的命令。
只包含对数据库数据起决定性作业的命令,不去管过程。比如对于一下命令:
set num 1
set num 2
set num 3
...
set num 99999
因为每次set命令都会覆盖之前的值,所以AOF重写功能生成的AOF文件只会包含set num 99999
命令。
用户可以通过执行BGREWRITEAOF命令或者设置相关的配置选项来触发AOF重写操作。
2.4.1 BGREWRITEAOF命令
用户可以通过执行BGREWRITEAOF命令显式地触发AOF重写操作,该命令是一个无参数命令:
BGREWRITEAOF命令是一个异步命令,Redis服务器在接收到该命令之后会创建出一个子进程,由它扫描整个数据库并生成新的AOF文件。当新的AOF文件生成完毕,子进程就会退出并通知Redis服务器(父进程),然后Redis服务器就会使用新的AOF文件代替已有的AOF文件,借此完成整个重写操作。
关于BGREWRITEAOF还有两点需要注意:
- 如果用户发送BGREWRITEAOF命令请求时,服务器正在创建RDB文件,那么服务器将把AOF重写操作延后到RDB文件创建完毕之后再执行,从而避免两个写硬盘操作同时执行导致机器性能下降。
- 如果服务器在执行重写操作的过程中,又接收到了新的BGREWRITEAOF命令请求,那么服务器将返回以下错误:
说明:
复杂度:O(N),其中N为Redis服务器所有数据库包含的键值对总数量。
2.4.2 AOF重写配置选项
用户除了可以手动执行BGREWRITEAOF命令创建新的AOF文件之外,还可以通过设置以下两个配置选项让Redis自动触发BGREWRITEAOF命令:
其中auto-aof-rewrite-min-size选项用于设置触发自动AOF文件重写所需的最小AOF文件体积,当AOF文件的体积小于给定值时,服务器将不会自动执行BGREWRITEAOF命令。在默认情况下,该选项的值为:
也就是说,如果AOF文件的体积小于64MB,那么Redis将不会自动执行BGREWRI-TEAOF命令。
至于另一个选项,它控制的是触发自动AOF文件重写所需的文件体积增大比例。举个例子,对于该选项的默认值:
表示如果当前AOF文件的体积比最后一次AOF文件重写之后的体积增大了一倍(100%),那么将自动执行一次BGREWRITEAOF命令。如果Redis服务器刚刚启动,还没有执行过AOF文件重写操作,那么启动服务器时使用的AOF文件的体积将被用作最后一次AOF文件重写的体积。
举个例子,如果服务器启动时AOF文件的体积为200MB,而auto-aof-rewrite-percentage选项的值为100,那么当AOF文件的体积增大至超过400MB时,服务器就会自动进行一次AOF重写。与此类似,在同样设置下,如果AOF文件的体积从最后一次重写之后的300MB增大至超过600MB,那么服务器将再次执行AOF重写操作。
说明:
配置文件位置:redis安装目录/redis.conf
2.5 AOF持久化的优缺点
与RDB持久化可能会丢失大量数据相比,AOF持久化的安全性要高得多:通过使用everysec选项,用户可以将数据丢失的时间窗口限制在1s之内。
但是与RDB持久化相比,AOF持久化也有相应的缺点:
- 首先,因为AOF文件存储的是协议文本,所以它的体积会比包含相同数据、二进制格式的RDB文件要大得多,并且生成AOF文件所需的时间也会比生成RDB文件所需的时间更长。
- 其次,因为RDB持久化可以直接通过RDB文件恢复数据库数据,而AOF持久化则需要通过执行AOF文件中保存的命令来恢复数据库(前者是直接的数据恢复操作,而后者则是间接的数据恢复操作),所以RDB持久化的数据恢复速度将比AOF持久化的数据恢复速度快得多,并且数据库体积越大,这两者之间的差距就会越明显。
- 最后,因为AOF重写使用的BGREWRITEAOF命令与RDB持久化使用的BGSAVE命令一样都需要创建子进程,所以在数据库体积较大的情况下,进行AOF文件重写将占用大量资源,并导致服务器被短暂地阻塞。
3. RDB-AOF混合持久化
由于RDB持久化和AOF持久化都有各自的优缺点,因此在很长一段时间里,如何选择合适的持久化方式成了很多Redis用户面临的一个难题。
- RDB持久化可以生成紧凑的RDB文件,并且使用RDB文件进行数据恢复的速度也非常快,但是RDB的全量持久化模式可能会让服务器在停机时丢失大量数据。
- 与RDB持久化相比,AOF持久化可以将丢失数据的时间窗口限制在1s之内,但是协议文本格式的AOF文件的体积将比RDB文件要大得多,并且数据恢复过程也会相对较慢。
为了解决这个问题,Redis从4.0版本开始引入RDB-AOF混合持久化模式,这种模式是基于AOF持久化模式构建而来的——如果用户打开了服务器的AOF持久化功能,并且将
选项的值设置成了yes,那么Redis服务器在执行AOF重写操作时,就会像执行BGSAVE命令那样,根据数据库当前的状态生成出相应的RDB数据,并将这些数据写入新建的AOF文件中,至于那些在AOF重写开始之后执行的Redis命令,则会继续以协议文本的方式追加到新AOF文件的末尾,即已有的RDB数据的后面。
换句话说,在开启了RDB-AOF混合持久化功能之后,服务器生成的AOF文件将由两个部分组成,其中位于AOF文件开头的是RDB格式的数据,而跟在RDB数据后面的则是AOF格式的数据,如图所示:
当一个支持RDB-AOF混合持久化模式的Redis服务器启动并载入AOF文件时,它会检查AOF文件的开头是否包含了RDB格式的内容:
- 如果包含,那么服务器就会先载入开头的RDB数据,然后再载入之后的AOF数据。
- 如果AOF文件只包含AOF数据,那么服务器将直接载入AOF数据。
下图展示了这一判断过程:
通过使用RDB-AOF混合持久化功能,用户可以同时获得RDB持久化和AOF持久化的优点:服务器既可以通过AOF文件包含的RDB数据来实现快速的数据恢复操作,又可以通过AOF文件包含的AOF数据来将丢失数据的时间窗口限制在1s之内。
配置文件位置:redis安装目录/redis.conf
4. 同时使用RDB持久化和AOF持久化
在Redis 4.0的RDB-AOF混合持久化功能出现之前,不少追求安全性的Redis使用者都会同时使用RDB持久化和AOF持久化,但随着RDB-AOF混合持久化功能的推出,同时使用两种持久化功能已经不再必要。
如果用户使用的是Redis 4.0之前的版本,那么同时使用RDB持久化和AOF持久化仍然是可行的,只要注意以下问题即可:
- 同时使用两种持久化功能需要耗费大量系统资源,系统的硬件必须能够支撑运行这两种功能所需的资源消耗,否则会给系统性能带来影响。
- Redis服务器在启动时,会优先使用AOF文件进行数据恢复,只有在没有检测到AOF文件时,才会考虑寻找并使用RDB文件进行数据恢复。
- 当Redis服务器正在后台生成新的RDB文件时,如果有用户向服务器发送BGREWRI-TEAOF命令,或者配置选项中设置的AOF重写条件被满足了,那么服务器将把AOF重写操作推延到RDB文件创建完毕之后再执行,以此来避免两种持久化操作同时执行并争抢系统资源。
- 同样,当服务器正在执行BGREWRITEAOF命令时,用户发送或者被触发的BGSAVE命令也会推延到BGREWRITEAOF命令执行完毕之后再执行。
总的来说,在数据持久化这个问题上,Redis 4.0及之后版本的使用者都应该优先使用RDB-AOF混合持久化;对于Redis 4.0之前版本的使用者,因为RDB持久化更接近传统意义上的数据备份功能,而AOF持久化则更接近于传统意义上的数据持久化功能,所以如果用户不知道自己具体应该使用哪种持久化功能,那么可以优先选用AOF持久化作为数据持久化手段,并将RDB持久化用作辅助的数据备份手段。
5. 无持久化
如果用户想要彻底关闭这一默认的RDB持久化行为,让Redis服务器处于完全的无持久化状态,那么可以在服务器启动时向它提供以下配置选项:
配置文件位置:redis安装目录/redis.conf
这样一来,服务器将不会再进行默认的RDB持久化,从而使得服务器处于完全的无持久化状态中。处于这一状态的服务器在关机之后将丢失关机之前存储的所有数据,这种服务器可以用作单纯的内存缓存服务器。
6. SHUTDOWN:关闭服务器
用户可以通过执行SHUTDOWN命令来关闭Redis服务器。
在默认情况下,当Redis服务器接收到SHUTDOWN命令时,它将执行以下动作:
- 停止处理客户端发送的命令请求。
- 根据服务器的持久化配置选项,决定是否执行数据保存操作:
- 如果服务器启用了RDB持久化功能,并且数据库距离最后一次成功创建RDB文件之后已经发生了改变,那么服务器将执行SAVE命令,创建一个新的RDB文件。
- 如果服务器启用了AOF持久化功能或者RDB-AOF混合持久化功能,那么它将冲洗AOF文件,确保所有已执行的命令都被记录到了AOF文件中。
- 如果服务器既没有启用RDB持久化功能,也没有启用AOF持久化功能,那么服务器将略过这一步。
- 服务器进程退出。
因为Redis服务器在接收到SHUTDOWN命令并关闭自身的过程中,会根据配置选项来决定是否执行数据保存操作,所以只要服务器启用了持久化功能,那么使用SHUTDOWN命令来关闭服务器就不会造成任何数据丢失。
6.1 通过可选项指示持久化操作
在默认情况下,服务器在执行SHUTDOWN命令时,是否执行持久化操作是由服务器的配置选项决定的。
但是在有需要时,用户也可以使用SHUTDOWN命令提供的save选项或者nosave选项,显式地指示服务器在关闭之前是否需要执行持久化操作:
如果用户给定的是save选项,那么无论服务器是否启用了持久化功能,服务器都会在关闭之前执行一次持久化操作。下表展示了服务器在不同持久化配置下,执行SHUTDOWN save命令时的行为。
如果用户给定的是nosave选项,那么服务器将不执行持久化操作,直接关闭服务器。在这种情况下,如果服务器在关闭之前曾经修改过数据库,那么它将丢失那些尚未保存的数据。
6.2 复杂度说明
复杂度:O(N),其中N为关闭服务器时需要持久化的键值对数量。
7. Redis持久化重点回顾
- Redis的持久化功能可以将存储在内存中的数据库数据以文件形式存储到硬盘,并在有需要时根据这些文件的内容实施数据恢复。
- RDB持久化是一种全量持久化方式,可以创建出经过压缩的时间点二进制快照文件,并通过载入文件中的二进制数据来实施数据恢复。这种持久化的优点是可以高效地生成文件并且快速地实施数据恢复,缺点则是文件生成间隔较长以及停机时数据丢失量较大。
- AOF持久化是一种增量式持久化功能,可以创建出协议文本格式的文件,文件中以协议形式记录了服务器执行过的所有命令,服务器可以通过重新执行文件中保存的命令来实施数据恢复。
- 在通常情况下,使用AOF持久化可以将停机时丢失数据的时间窗口控制在1s之内,但也需要定期对AOF文件执行重写操作,使得AOF文件的体积可以维持在合理的范围之内。除此之外,使用AOF文件实施数据恢复的耗时要比使用RDB文件实施数据恢复的耗时更久。
- 通过使用Redis 4.0新增的RDB-AOF混合持久化功能,用户可以同时获得RDB持久化和AOF持久化各自的优点:服务器既可以通过RDB数据实现快速的数据恢复,又可以通过AOF数据来有效地限制丢失数据的时间窗口。
- Redis 4.0及以上版本的使用者应该优先选用RDB-AOF混合持久化作为数据持久化手段,而旧版Redis的使用者则应该优先选用AOF持久化作为数据持久化手段,并将RDB持久化用作辅助的数据备份手段。
- 处于无持久化状态的Redis服务器在关机之后将丢失关机之前存储的所有数据。
以上是关于Redis 进阶 -- 持久化(RDB持久化AOF持久化RDB-AOF混合持久化无持久化)的主要内容,如果未能解决你的问题,请参考以下文章