字节面试:Redis为什么要持久化?有几种方式?

文章目录

Redis为什么需要持久化?

Redis是内存数据库,断电即失,这决定了它必须带有持久化的功能。常见持久化方式有两种,分别是rdb与aof。断电即失使得rdb模式下服务器宕机或redis进程意外停止的时候,会丢失部分数据。

持久化分类

Redis分类分为RDBAOF 两种,由于这两种问题都存在问题,后续Redis推出了混合持久化的方式.

RDB(快照snapshot)

RDB文件的触发机制,简单来说,就是决定何时自动创建一个数据库的备份文件(我们称之为RDB文件)的过程。这个机制会在以下几个条件下触发:

  1. N 秒内数据集至少有 M 个改动(配置文件中可配,最常见的触发方式)
  2. 执行flushall命令
  3. 退出redis

以上都会生成备份文件dump.rdb

有了rdb文件后,怎么把rdb文件还原回来?很简单**将rdb文件放在redis的启动目录即可**,生成时默认在启动目录,可以通过config get dir 查看当前文件夹,默认配置基本就够用。

AOF (Append Only File)

该模式下保存的是所有redis的写命令,读的命令不记录。当redis重启的时候会将保存的命令重新执行一遍。恢复原来的数据。AOF的文件名是appendonly.aof。可以配置 Redis 多久才将数据 fsync 到磁盘一次,一般有三个选项:默认是每秒fsync一次,这种策略可以兼顾速度和安全。

由于Redis的只记录写命令,为了去除一些冗余命令,使用AOF作为持久化机制时会有自动重写与手动重写的两种优化方式。先看看什么时候会产生冗余命令,假设:

  1. 对一个整数键进行自增操作,如 INCR key2,写入 AOF 文件后键的值变为 1。
  2. 接着再次执行 INCR key2,键的值变为 2。
  3. 然后执行 DECR key2,键的值又变回 1。

在这个过程中,第二次 INCR 和 DECR 操作产生的命令对于最终数据库状态来说是冗余的,因为只需要第一次 INCR 操作的命令就可以恢复到最终的数据库状态。

除了自动重写,当然AOF还可以手动重写,进入redis客户端执行命令bgrewriteaof重写AOF 。这个过程会fork出一个子进程去做(与bgsave命令类似),不会对redis正常命令处理有太多影响。

AOF VS RDB

对比项 AOF RDB
可靠性 高,因为记录了所有写操作命令,可通过重放命令恢复数据。即使出现故障,丢失的数据相对较少。 相对较低,取决于保存 RDB 的时间间隔,可能会丢失间隔期间的数据。
性能 写入操作会带来一定的性能开销,尤其是在always 同步策略下。 在保存 RDB 时会fork子进程,会有短暂的性能影响,但总体对性能的影响相对较小。
存储空间占用 通常比 RDB 大,因为记录了所有写操作。 相对较小,只保存数据库在某一时刻的快照。
恢复时间 相对较长,因为需要重放所有的写操作命令。 通常较短,因为只需加载快照文件即可恢复数据库状态。

混合持久化

通过上方的表格可以清晰的看到,混合持久化要解决的问题是RDB的可靠性低,AOF的恢复时间慢的问题。

重启 Redis 时,很少使用 RDB来恢复内存状态,因为会丢失大量数据 。通常使用AOF日志重放,但是重放AOF日志性能相对 RDB来说要慢很多,这样在 Redis 实例很大的情况下,启动需要花费很长的时间。 Redis 4.0 为了解决这个问题,带来了一个新的持久化选项------混合持久化。 通过如下配置可以开启混合持久化(必须先开启aof ):aof‐use‐rdb‐preamble yes

如果开启了混合持久化,AOF在重写时,不再是单纯将内存数据转换为RESP命令写入AOF文件,而是将重写这一刻之前的内存做RDB快照处理,并且将RDB快照内容和增量的AOF修改内存数据的命令存在一 起(rdb在前,aof在后,都写入新的AOF文件,新的文件一开始不叫appendonly.aof,等到重写完新的AOF文件才会进行改名,覆盖原有的AOF文件,完成新旧两个AOF文件的替换。

于是在** Redis 重启的时候,可以先加载 RDB 的内容,然后再重放增量 AOF 日志就可以完全替代之前的 AOF 全量文件重放,因此重启效率大幅得到提升**。

混合持久化AOF文件结构如下:

扩展1:生成RDB快照命令对比

对比项 SAVE BGSAVE
执行方式 阻塞 Redis 服务器,直到 RDB 文件创建完毕 在后台异步执行,不阻塞服务器
对性能影响 严重影响服务器性能,阻塞所有客户端请求 对服务器性能影响相对较小,不影响正常服务
资源消耗 相对较少 会 fork 子进程,消耗一定系统资源,特别是内存
数据一致性 能保证数据一致性,但执行过程中可能延迟新写入操作 由于在后台执行,数据一致性可能稍弱
适用场景 无高并发请求时,如重要数据备份或服务器维护前 生产环境,服务器运行期间需创建 RDB 快照且不能中断服务

总的来说,<font style="color:rgba(0, 0, 0, 0.85);">BGSAVE</font>是一种更常用的生成 RDB 快照的方式,因为它不会阻塞服务器,对性能的影响较小 。但是,在某些特殊情况下,如需要立即创建一个可靠的 RDB 快照且可以接受服务器暂时不可用时,可以使用<font style="color:rgba(0, 0, 0, 0.85);">SAVE</font>命令。

扩展2:模拟断电恢复数据

先删除原来的持久化文件

模拟写操作,往redis中写入数据

此时可以看到重新生成了持久化文件

直接关闭进程,重启redis,根据上文可以知道redis重启会自动将持久化的数据恢复。使用get命令获取到了断电之前设置的数据

扩展3:设置持久化方式为AOF

首先Redis默认采用的是RDB的持久化方式,所以要把图中的no改为yes

相关推荐
Elaine20239142 分钟前
零碎04 MybatisPlus自定义模版生成代码
java·spring·mybatis
一二小选手1 小时前
【MyBatis】全局配置文件—mybatis.xml 创建xml模板
xml·java·mybatis
fpcc1 小时前
redis6.0之后的多线程版本的问题
c++·redis
刘九灵1 小时前
Redis ⽀持哪⼏种数据类型?适⽤场景,底层结构
redis·缓存
刘大浪2 小时前
后端数据增删改查基于Springboot+mybatis mysql 时间根据当时时间自动填充,数据库连接查询不一致,mysql数据库连接不好用
数据库·spring boot·mybatis
蓝染-惣右介4 小时前
【MyBatisPlus·最新教程】包含多个改造案例,常用注解、条件构造器、代码生成、静态工具、类型处理器、分页插件、自动填充字段
java·数据库·tomcat·mybatis
登云时刻4 小时前
Kubernetes集群外连接redis集群和使用redis-shake工具迁移数据(一)
redis·kubernetes·bootstrap
武子康5 小时前
Java-07 深入浅出 MyBatis - 一对多模型 SqlMapConfig 与 Mapper 详细讲解测试
java·开发语言·数据库·sql·mybatis·springboot
一二小选手5 小时前
【Mybatis】@Param注解 resultMap手动映射
java·mybatis
J老熊6 小时前
JavaFX:简介、使用场景、常见问题及对比其他框架分析
java·开发语言·后端·面试·系统架构·软件工程