Redis是一个内存中的键值存储系统,虽然它主要将数据保存在内存中以提供高性能的读写操作,但它也提供了多种持久化机制,以确保在服务器重启或崩溃后,数据不会丢失。Redis主要支持两种持久化方式:RDB(Redis Database Backup快照持久化)和AOF(Append-Only File日志持久化)。
1、RDB(Redis Database Backup,快照持久化)
(1)、原理
RDB是一种快照持久化方式,它通过定期将Redis内存中的数据集保存到磁盘上的一个二进制文件中(通常命名为dump.rdb)。RDB文件是一个紧凑的二进制文件,包含了某个时间点的完整数据快照。当Redis重新启动时,它可以加载这个RDB文件,恢复到上次保存的时间点。
(2)、优点
- 性能高效:RDB持久化是通过fork一个子进程来完成的,子进程负责将数据写入磁盘,而主进程继续处理客户端请求。因此,RDB持久化对Redis的性能影响相对较小。
- 恢复速度快:由于RDB文件是二进制格式且包含完整的数据快照,因此在Redis重启时,加载RDB文件的速度非常快,RDB恢复数据远远快于AOF的方式。
- 适合备份:RDB文件是紧凑的二进制文件,节省磁盘空间,非常适合用于备份和灾难恢复。你可以定期将 RDB文件备份到其他存储介质或云存储中。
(3)、缺点
- 数据丢失风险:RDB是基于快照的持久化方式,因此它的持久化频率较低。如果Redis在两次快照之间崩溃,可能会导致部分数据丢失。例如,如果你配置了每5分钟进行一次快照,那么在崩溃时最多可能丢失5分钟的数据。
- 内存膨胀:子进程备份数据的时候,内存中的数据会被克隆一份,会导致内存短暂膨胀到2倍的大小。
- 不适合频繁更新的场景:如果Redis中的数据更新非常频繁,RDB快照可能会变得非常大,并且频繁的快照操作可能会增加I/O压力。
(4)、配置示例
可以在 redis.conf文件中配置RDB的触发条件。
1、配置文件示例
(1)、触发备份条件(save)
save 60 1
save 300 10
save 900 1000
以上3行的解释如下:
- 每60秒内至少1个键发生变化时,保存一次快照
- 每300秒内至少有10个键发生变化时,保存一次快照
- 每900秒内至少有1000个键发生变化时,保存一次快照
配置理解说明:
以save 300 10为例说明下:
情况1:
如果300秒内,发生了10次或更多的写入操作(增删改都算),会触发一次RDB持久化。*注意是只会触发一次,即使300秒内发生了50次写操作也只会RDB持久化1次。*一旦触发了RDB持久化后,写操作计数器就会被重置为0,重新开始计数。
在解释下:
当300秒写操作发生50次时,计数结果就是50,等到300秒间隔到了,会触发一次条件校验,此时50>=10成立,触发RDB持久化,同时计算器重置为0。在继续等待300秒进行下一次校验。
情况2:
如果300秒内,写入操作不足10次呢?这里假设每个300秒内只有2次写操作的情况。
Redis 的行为如下:
- 第一个300秒:发生了2次写操作。由于写操作次数不足10次,Redis不会触发RDB持久化。计数器的值为2。
- 第二个300秒:又发生了2次写操作。此时,计数器的值变为 4(未触发RDB持久化操作,计算器值不会改变,所以累计为2+2=4)。由于写操作次数仍然不足10次,Redis仍然不会触发RDB持久化。
- 第三个300秒:再次发生了2次写操作。此时,计数器的值变为6。 Redis仍然不会触发RDB持久化。
- 第四个300秒:再次发生了2次写操作。此时,计数器的值变为 8 。Redis仍然不会触发 RDB持久化。
- 第五个300秒:再次发生了2次写操作。此时,计数器的值变为10。现在,写操作次数达到了10次,因此Redis会触发一次RDB持久化,并将计数器重置为 0。
在解释下:
当第一个300秒内写操作发生2次时,计数结果是2,触发校验条件,但此时条件不满足,不会进行RDB持久化,同时计数器的值不会重置为0,会继续保留。直到第5个300秒周期校验时,此时10>=10成立,触发1次RDB持久化,计算器重置为0。之后再继续如上处理。
可配置多行说明:
相信这两种情况分析下来,就应该比较清晰RDB的触发机制了吧。还有一点需要注意下,
如上的save配置是可以配置多行的。配置示例中的3行,或者自定义其他模式的行都是可以的。配置的每一行都相当于开启一个计时器,只要有任意一行符合标准,就会触发一次RDB持久化操作。
(2)、其他配置
1、指定备份文件的名称
dbfilename dump.rdb
说明:
默认rdb的备份名称dump.rdb,这里也可以自定义修改。
2、指定备份文件的路径
dir ./
说明:
默认就是当前文件夹,即和配置文件在同一层级的目录中。
3、备份错误时是否停止redis的写操作
stop-writes-on-bgsave-error yes
说明:
这是一个很重要的配置项,用于控制当RDB持久化(即BGSAVE操作)失败时,Redis是否停止处理写操作。
配置项的默认值是yes,表示当BGSAVE失败时,Redis会停止处理新的写操作,这意味着在BGSAVE失败期间,所有写命令(如SET、DEL等)都会被拒绝,并返回错误信息给客户端。这样做可以让用户很快发现问题,进而防止数据进一步丢失或不一致。(通常这种BGSAVE出现异常都是在内存不足的情况下才会发生)
4、rdb备份是否开启压缩
rdbcompression yes
说明:
在备份rdb文件时,如果设置为yes的话,redis会采用LZF算法进行压缩。这种压缩可以减少文件内存的占用,但是会消耗CPU处理压缩算法。如果你不想消耗CPU来进行压缩的话,可以设置为关闭no。默认是yes,推荐yes。
5、校验备份文件的完整性
rdbchecksum yes
说明:
该配置用于检查rdb备份文件的完整性。存储快照后,还可以让redis使用CRC64算法来进行数据校验,但是这样做会增加大约10%的性能消耗,如果希望获取最大的性能提升,可以关闭此功能。推荐yes。
2、命令行示例
还可以通过save或bgsave命令手动触发RDB快照。
save 是使用主进程去执行备份,会阻塞备份期间的其他所有命令
bgsave 启动子进程执行备份,不会阻塞
示例如下:
(5)、工作流程
1、触发条件:当满足save配置中的条件时,Redis会触发RDB持久化。
2、fork(复制)子进程:Redis主进程会fork一个子进程,子进程负责将内存中的数据写入临时RDB文件。
3、写入磁盘:子进程将内存中的数据逐字节写入临时RDB文件,完成后替换旧的RDB文件。
4、主进程继续工作:在整个过程中,主进程继续处理客户端请求,不受影响。
5、重启恢复:当Redis重新启动时,它会自动加载最新的RDB文件,恢复到上次保存的时间点。
(6)、内存原理
1、当redis需要RDB持久化操作时,会先fork一个子进程(简单理解:操作系统此时运行了两个redis服务,主进程处理客户端读写操作,子进程处理数据备份)。
2、主进程和子进程之间是共享数据的(即:redis内存数据是一份,两个进程都可以访问,两个进程实际上共享了这块内存的页表(相当于内存的目录))。此时两个进程对页表都只能进行读操作。
3、子进程备份数据,仅读取页表数据写入临时文件。(注意:如果之前存在备份过的RDB文件,子进程不会直接在该文件上操作。而是去创建临时文件用于存储本次备份的数据,等到备份完成时,会将临时文件替换之前的RDB备份文件。)
4、主进程读操作正常,写操作就不能再使用共享页表内了,否则就会被子进程直接备份走了。此时的写操作会先从页表中读取目标数据到临时的内存中,在临时的内存中在进行写操作,等到RDB结束后,在将临时内存数据合并到页表中。
(即:主进程在新的内存空间处理写操作,读操作会结合临时内存和页表一起查询,等待RDB结束,再将临时内存合并到页表内)
示例图如下:
(7)、RDB的备份恢复步骤
1、先通过CONFIG GET dir查询rdb文件的目录,这其实就是查的redis.conf文件当中通过dir设置的目录
2、停止Redis
3、找到目标路径下的备份文件(dump.rdb),将备份文件数据加载到redis的内存中。
4、重新启动redis服务
(8)、适用场景
- 数据更新不频繁,允许一定程度的数据丢失。
- 需要快速重启和恢复。
- 需要定期备份数据。
2、AOF(Append-Only File,追加日志持久化)
(1)、原理
AOF是一种日志持久化方式,它通过记录Redis执行的每个写命令(如SET、LPUSH等),并将这些命令追加到AOF文件中(通常命名为appendonly.aof)。当Redis重新启动时,它会重新执行AOF文件中的所有命令,从而恢复数据。
相当于对一个空的Redis实例顺序执行所有的指令,也就是「重放」,来恢复Redis的内存数据。
(2)、优点
- 数据安全性高:AOF持久化的频率可以设置为每次写操作后立即追加到文件中(appendfsync always),因此即使Redis突然崩溃,最多只会丢失1条命令的数据。这使得AOF比RDB更加安全,尤其是在数据一致性要求较高的场景下。
- 适合频繁更新的场景:AOF记录的是每个写命令,因此它非常适合频繁更新的场景。即使数据更新非常频繁,AOF也能保证数据的完整性。
- 可读性强:AOF文件是纯文本格式,记录的是Redis的命令。因此,你可以手动编辑AOF文件,修复某些错误或删除不必要的命令。
(3)、缺点
- 文件体积大:由于AOF记录的是每个写命令,因此AOF文件的体积可能会非常大,尤其是当Redis中的数据更新频繁时。较大的AOF文件会影响Redis的启动速度和内存使用。
- 性能开销较大:AOF持久化的频率越高,I/O开销越大。如果设置为每次写操作后立即追加到文件中(appendfsync always),可能会对Redis的性能产生一定的影响。
- 重写机制:为了防止AOF文件过大,Redis提供了AOF重写机制。AOF重写会生成一个新的AOF文件,该文件只包含恢复数据所需的最少命令。然而,AOF重写过程也会消耗一定的CPU和I/O资源。
(4)、配置示例
你可以在redis.conf文件中启用AOF并配置其同步策略。
1、配置文件示例
第一步:启用AOF持久化
appendonly yes
第二步:设置AOF文件名称
appendfilename "appendonly.aof"
说明:
该文件的存储路径和之前说rdb时一样,也是dir ./配置的路径,默认和配置文件同一层级。
第三步:设置AOF同步策略
appendfsync always 每次写操作后立即同步到磁盘,最安全但性能最低
appendfsync everysec 每秒同步一次,默认配置,兼顾安全性和性能(推荐)
appendfsync no 不主动同步,依赖操作系统刷新,性能最高但最不安全
第四步:启用AOF重写
auto-aof-rewrite-percentage 100
auto-aof-rewrite-min-size 64mb
说明:
auto-aof-rewrite-min-size表示aof文件重写的最小内存,即:当aof文件达到64M时,开始触发重写,也就是第一次触发重写。
auto-aof-rewrite-percentage表示自动重写时aof内存大小的比例,如示例为100%,因为最小设置为64M,所以当下一次aof文件内存达到128M时在触发重写,在下一次192M时触发重写,以此类推。
如果将百分比值设置为 0 就表示关闭 AOF 自动重写功能。
第五步:重写时是否执行appendfsync同步操作
no-appendfsync-on-rewrite no
说明:
默认配置为no。当AOF重写时,会根据同步的配置将AOF缓冲区中的数据做同步到磁盘aof文件中,这在很大程度上保证了数据的安全性。但可能会发生阻塞,造成性能问题。
如果配置yes,AOF重写时,缓冲期数据不写入aof文件,用户请求不会阻塞,但是在这段时间如果宕机会丢失这段时间的缓存数据。
2、命令行示例
手动触发重写aof文件
BGREWRITEAOF
(5)、工作流程
1、记录写命令:每当Redis执行一个写命令时,它会将该命令追加到AOF缓冲区(aof_buf)。
2、同步到磁盘:根据appendfsync的配置,Redis会决定何时将AOF缓冲区的命令同步到AOF磁盘中。可以选择每次写操作后立即同步、每秒同步一次,或者依赖操作系统的刷新机制。
3、AOF重写:为了防止AOF文件过大,Redis会定期触发AOF重写。AOF重写会生成一个新的AOF文件,该文件只包含恢复数据所需的最少命令。重写过程是通过fork一个子进程来完成的,子进程负责生成新的AOF文件,而主进程继续处理客户端请求。
4、重启恢复:当Redis重新启动时,它会读取AOF文件并重新执行其中的所有命令,从而恢复数据。
流程示意图:
(6)、使用建议
由于RDB可能会丢失大量数据,AOF重启加载速度问题(官方不建议单独使用AOF,因为可能会出现BUG)。
所以在生产环境中,官方推荐2个都启用。启用AOF持久化,并将其同步策略设置为everysec,以在性能和数据安全性之间取得平衡。同时,定期启用RDB快照,用于备份和灾难恢复。
(7)、适用场景
- 数据更新频繁,要求尽可能高的数据安全性。
- 需要最小化数据丢失的风险。
- 可以接受较大的AOF文件和较慢的恢复速度。
3、Redis 4.0混合持久化
(1)、概述
重启Redis时,使用rdb来恢复内存可能会丢失大量数据。所以通常使用AOF日志重放,但是重放AOF日志性能相对rdb来说要慢很多,这样在Redis实例很大的情况下,启动需要花费很长的时间。
Redis 4.0之后为了解决这个问题,带来了一个新的持久化选项——混合持久化。将rdb文件的内容和增量的AOF日志文件存在一起。这里的AOF日志不再是全量的日志,而是自持久化开始到持久化结束的这段时间发生的增量AOF日志,通常这部分AOF日志很小。
示意图如下:
(2)、混合持久化和混合使用区别
**同时使用RDB和AOF:**如果同时配置rdb和aof,Redis会默认使用aof的方式进行数据恢复(aof文件包含了更全的数据),只有当AOF异常时,才会使用RDB的方式恢复数据。
**混合持久化:**同时使用两种方式(AOF文件中包含了一个全量的RDB文件,和部分aof命令日志),先使用全量的RDB恢复,后采用增量的AOF命令日志恢复。
(3)、混合持久化配置
在4.0及之后的Redis版本中,多出了aof-use-rdb-preamble配置。该配置用于优化AOF(Append Only File)文件的加载性能。它允许Redis在AOF文件中包含一个RDB快照(即RDB文件的内容),从而在Redis启动时通过加载RDB快照来加速数据恢复过程。
在4.0版本中,默认值是关闭的,在5.0版本中默认是开启的。
配置文件:开启混合持久化
aof-use-rdb-preamble yes
(4)、混合持久化优缺点
1、优点:
混合持久化结合了RDB和AOF持久化的优点,开头为RDB的格式,使得Redis可以更快的启动,同时结合AOF的优点,有减低了大量数据丢失的风险。
2、缺点:
- AOF文件中添加了RDB格式的内容,使得AOF文件的可读性变得很差;
- 兼容性差,如果开启混合持久化,那么此混合持久化AOF文件,就不能用在Redis 4.0之前版本了。
4、总结
Redis的持久化默认策略是RDB,因为默认AOF的方式是关闭的,需要我们手动开启和配置;
建议配置:RDB和AOF2种都启用,启用AOF同步策略设置为everysec。如果是支持混合持久化的Redis版本,建议也开启混合持久化。(推荐)
学海无涯苦作舟!!!