Redis篇-16--持久化篇(RDB,AOF,混合持久化,最佳策略)

server/2024/12/19 4:00:57/

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版本,建议也开启混合持久化。(推荐)

学海无涯苦作舟!!!


http://www.ppmy.cn/server/151344.html

相关文章

概率论得学习和整理23:EXCEL 数据透视表基础操作

目录 1 选择数据,插入数据透视表 2 选择数据透视表生成位置 3 出现了数据透视表的面板 4 数据透视表的基本结构认识 4.1 交叉表/列联表 4.2 row, column, cell 一个新增的筛选器,就这么简单 4.3 可以只添加 rowcell/值 ,也可以colu…

嵌入式跨平台工具链终极方案

嵌入式跨平台工具链终极方案 1. 解决烦人的编译,从编译器开始2. T0级别的代码编辑器IDE3. git linus之父开发神奇的分布式代码管理工具 我们从8051开始学习嵌入式,用过了不少IDE,比如经典的keil和IAR,但是这些IDE都不便宜&#xf…

Excel拆分脚本

Excel拆分 工作表按行拆分为工作薄 工作表按行拆分为工作薄 打开要拆分的Excel文件,使用快捷键(AltF11)打开脚本界面,选择要拆分的sheet,打开Module,在Module中输入脚本代码,然后运行脚本 Su…

Android OnTouchListener OnTouchEvent OnClickListener三者之间的关系?

在android开发过程中,我们时常会需要与用户进行信息交互,就会接触到android的两种事件处 理机制:事件回调机制(onEvent)和事件监听机制(onListener),那么他们两者之间到底有什 么区别…

划分WLAN的三种主要方法,基于WLAN,基于IP,基于端口

划分WLAN的三种主要方法包括基于交换机端口的划分、基于MAC地址的划分和基于L3的IP划分‌。 ‌基于交换机端口的划分‌:这是最常见的VLAN划分方法。通过将交换机上的特定端口分配给不同的VLAN,可以实现网络的不同部分相互隔离。每个端口只能属于一个VLAN…

论文信息收集1217

系列博客目录 文章目录 系列博客目录1.《A low-rank support tensor machine for multi-classification》2.Supervised Learning by Low Rank Estimation on Tensor Data.3.Tensor Regression Using Low-rank and Sparse Tucker Decompositions 张量回归:低秩和稀疏…

MYSQL执行一条update语句,期间发生了什么

客户端先通过连接器建立连接,连接器自会判断用户身份; 因为这是一条 update 语句,所以不需要经过查询缓存,但是表上有更新语句,是会把整个表的查询缓存清空的,所以说查询缓存很鸡肋,在 MySQL 8…

查询三网话费余额接口,移动话费余额接口、电信话费余额接口、联通话费余额的接口+html前端查询UI界面

PHP是直接请求的接口&#xff0c;HTML代码也是直接请求的接口。如果HTML想上线运行&#xff0c;还是需要做下安全的。 下边是PHP代码 <?php // 定义API接口地址和参数 $apiUrl "https://api.taolale.com/api/Inquiry_Phone_Charges/get"; //API文档地址&…