Redis 持久化机制

文章目录

1.引言

Redis 作为内存数据库,数据默认存储在内存中 ------ 一旦服务器重启、断电或崩溃,内存数据会全部丢失。为解决这一问题,Redis 设计了两种核心持久化方案:RDB(快照持久化)和 AOF(日志持久化),后续又推出 "混合持久化" 结合两者优势。本文将从原理、配置、操作到优缺点对比,全面解析 Redis 持久化机制,帮你理解 "如何在性能与数据安全性之间找到平衡"。

2.认识持久化

首先明确持久化的本质 ------ 将 Redis 内存中的数据定期或实时写入磁盘,确保 "服务器重启后,能从磁盘文件恢复数据",对应 MySQL 事务的 "持久性(Durability)" 特性。、

持久性--》重启主机后,数据是否存在。

存储在磁盘上--》持久

存储在内存上--》不持久

redis 是一个内存数据库,把数据存储在内存上的。

为了保证持久性,也会把数据存储在磁盘上。不过读取数据依旧是在内存,磁盘的数据只是在redis重启时用来恢复内存中的数据的。

插入数据时--》写入内存&磁盘

读取数据时--》从内存中读取

重启redis时--》从磁盘加载数据到内存

(代价是用了更多的空间)

写入磁盘有不同的策略,可能导致内存和磁盘中的数据有小概率存在差异。

redis持久化策略

1)RDB ----》redis database (定期备份)

2)AOF ----》 Append Only File (实时备份)

3. RDB 持久化:定期生成内存快照

RDB定期把redis内存中的所有数据,写入磁盘中,生成一个"快照"。后续redis一旦重启了,就会根据刚才的"快照" 把内存中的数据恢复。

3.1 RDB 的触发方式:手动与自动

手动触发:适合临时备份

save命令:同步执行快照生成,期间会阻塞 Redis(无法处理其他客户端请求),仅适合测试环境,生产环境严禁使用;

bash 复制代码
127.0.0.1:6379> save  # 阻塞Redis,直到快照生成完成
OK

bgsave命令:异步执行快照生成(通过 fork 创建子进程),父进程继续处理客户端请求,无阻塞风险,是生产环境常用方式;

bash 复制代码
127.0.0.1:6379> bgsave  # 立即返回OK,子进程后台生成快照
Background saving started

自动触发

在redis配置文件中,设置redis多久/产生多少修改 后触发

60min内修改1次--》快照

5min内修改100次--》快照

60s内修改10000次 ---》快照

可以修改上述数据,不过生成rdb快照成本较高,所以修改要保证操作执行不能太频繁。

正是因为rdb生成的不能太频繁,所以快照里的数据 和 实时数据 可能存在偏差。

如果在间隔(60s)内,redis收到大量数据 导致 服务器挂了,就会丢失这60s的数据。

  1. 先判断是否有其他进程正在执行bgsave,有则直接返回
  2. 没有就通过fork创建子进程,执行bgsave
  3. 子进程负责写文件,生成快照。父进程继续接收客户端其他请求
  4. 子进程完成持久化后,通知父进程,父进程更新统计信息后,回收子进程

子进程生成快照时,会生成rdb文件,是放在redis的工作目录中的。

在redis配置文件中,可以设置


后续redis重启,就会尝试加载这个rdb文件

当执行 生成rdb镜像 操作时,会先把生成的快照数据保存到一个临时文件中,当这个快照文件生成完毕后,再删除之前的rdb文件,把新删除的临时rdb文件改成 dump.rdb。

---》 自始至终,rdb文件都只有一个

3.2 rbd效果演示

redis的工作目录


手动执行(一般不执行save)



插入数据进行写快照操作后,rdb文件发生变化

之后重启redis,内存中就会加载rdb文件中的内容,恢复之前的状态

插入新的key,不手动执行bgsave

除了配置的自动触发规则,当正常退出redis服务器时,也会触发rdb操作。

如果是异常重启(kill -9 或者 服务器断电)此时redis服务器来不及生成rdb,内存中尚未保存的数据就会消失。

观察rdb文件的替换

bgsave流程是创建子进程,子进程完成持久化操作,把数据写入新的文件,然后用新文件代替旧文件。(如果直接使用save则不会触发 子进程&文件替换 逻辑,会直接在当前进程中写入数据)

不过子进程完成持久化的操作不好观察,新旧文件替换比较好观察。

可以使用Linux 的 stat命令,查看文件的inode编号,来观察新旧文件的替换。

Linux文件系统:

超级块(存放管理信息)

inode区(存放inode节点,每个文件都会分配一个innode 数据结构,包含文件的各种元数据)

block区 (存放 文件 的数据内容)

通过配置自动生成rdb快照

修改配置后要重启redis服务器才能生效。想要立刻生效也可以通过命令的方式来修改

bash 复制代码
CONFIG SET save "60 2"

save " " 关闭自动生成快照

手动改坏rdb文件

手动改坏rdb文件(打开redis.conf,手动改)

要通过kill -9 干掉进程,不能直接重启,因为正常重启在关闭前会生成快照。

改坏文件末尾--》对redis重启没什么影响,只是最近保存的数据会丢失。

改坏中间的文件--》发现redis重启不了。

当redis挂了,看看redis的日志,看看发生了什么


在rdb恢复过程中出现问题。

rdb是二进制文件,直接把坏的rdb文件给redis服务器去使用,得到的结果是不可预期的。

可能服务器正常启动,得到的数据可能对 可能错

也可能redis服务器启动失败。

可以通过redis通过的rdb检查工具,检查rdb文件格式是否符合要求

可以看到,这是一个软链接,redis服务器相当于 rdb检查工具的快捷方式。

运行的时候,通过加入选项来以检查工具的方式运行。不加选项就是启动redis服务器。

可以看到检测结果,EOF:end of File,读取文件末尾时遇到问题--》rdb文件损坏

3.3 rdb小结

  1. RDB 是一个紧凑压缩的二进制文件,代表 Redis 在某个时间点上的数据快照。非常适用于备份,全量复制等场景。比如每 6 小时执行bgsave 备份,并把 RDB 文件复制到远程机器或者文件系统中(如 hdfs)用于灾备。
  2. Redis 加载 RDB 恢复数据远远快于 AOF 的方式。
  3. RDB 方式数据没办法做到实时持久化 / 秒级持久化。因为 bgsave 每次运行都要执行 fork创建子进程,属于重量级操作,频繁执行成本过高。
  4. RDB 文件使用特定二进制格式保存,Redis 版本演进过程中有多个 RDB 版本,兼容性可能有风险。

4.AOF 持久化:实时记录操作日志

AOF 是 Redis 的 "实时持久化" 方案,核心是 "将每一条修改数据的命令(如set、hset)以文本格式追加到 AOF 文件中",类似 MySQL 的 binlog,确保 "每一条命令都不丢失"。

4.1 AOF 的开启与配置

默认情况下 AOF 是关闭的,需修改redis.conf开启:

bash 复制代码
# 开启AOF(默认no,改为yes)
appendonly yes
# AOF文件名(默认appendonly.aof)
appendfilename "appendonly.aof"
# AOF文件存储路径(与RDB相同,默认/var/lib/redis)
dir /var/lib/redis


4.2 AOF 的核心:缓冲区刷新策略

AOF 并非 "每条命令立即写入磁盘",而是先写入 "内存缓冲区(aof_buf)",再按配置的 "刷新策略" 将缓冲区数据同步到磁盘。Redis 提供 3 种刷新策略,配置项为appendfsync:

策略值 含义 数据安全性 性能影响
always 每执行一条命令,立即刷新缓冲区到磁盘 最高(仅丢失操作系统崩溃数据) 最低(频繁磁盘 I/O,适合金融场景)
everysec 每秒刷新一次缓冲区到磁盘(默认策略) 较高(最多丢失 1 秒数据) 中等(平衡安全与性能)
no 由操作系统决定何时刷新(通常 30 秒) 最低(可能丢失几十秒数据) 最高(适合非核心数据)

默认是everysec

4.3 重写机制(瘦身 AOF 文件)

aof文件持续增长,体积越来越大,会影响到redis下次的启动时间。(redis启动时读取aof文件恢复内容)

但是aof中的文件,有一些是冗余的

redis存在一个机制,能剔除aof文件的冗余,达到文件 瘦身 的效果。

aof的重写机制(rewrite)和 rbd一样也分为手动触发 和 自动触发

重写的触发方式

  • 手动触发:执行bgrewriteaof命令,异步重写(类似bgsave,通过 fork 子进程执行);
bash 复制代码
127.0.0.1:6379> bgrewriteaof  # 后台重写AOF文件
Background append only file rewriting started
  • 自动触发:Redis 根据 AOF 文件大小自动触发,配置项如下:
bash 复制代码
# AOF文件大小超过"基准大小"的100%(即翻倍)时触发重写
auto-aof-rewrite-percentage 100
# 基准大小:AOF文件最小重写阈值(默认64MB),低于此值不触发
auto-aof-rewrite-min-size 64mb

重写流程(与bgsave类似,但有缓冲区优化)

  1. 父进程判断:检查是否有bgsave或 AOF 重写进程在运行,若有则等待;
  2. 创建子进程:父进程fork子进程,子进程读取内存数据,生成最简 AOF 命令,写入临时文件;
  3. 父进程处理新命令:重写期间,父进程将新的修改命令同时写入 "原 AOF 缓冲区" 和 "重写缓冲(aof_rewrite_buf)";
  4. 合并缓冲区:子进程重写完成后,父进程将 "重写缓冲区" 的命令追加到临时文件;
  5. 替换旧文件:临时文件重命名为appendonly.aof,替换旧文件,重写完成。

重写的时候,不关心aof文件原来有什么,只需要把内存中当前的数据读取出来,以aof的格式写道另一个aof文件中。

AOF 重写时是根据内存中的最终数据结果,反向生成 "能直接得到这个结果" 的最简指令。

fork创建子进程的一瞬间--》子进程继承了fork时的内存状态--》根据内存状态反推 最简指令 ---》写入新的aof中。
父进程把fork之后的数据以aof的格式写入到aof_rewrite_buf中--》之后追加到子进程的新aof中 ---》再就可以替换旧aof文件了

追加的aof数据可能存在冗余,因为是实时根据内存反推的指令,没有剔除冗余的操作。

此处子进程写入数据类似rdb生成快照

不过rdb是以二进制的方式生成的,aof重写则是按照文本的格式生成的。

注意:

执行bgrewriteaof时,redis已经在进行aof重写了 ---》直接返回

redis在生成rdb文件的快照--》等待rdb生成完快照,再进行aof重写

rdb对于fork之后的数据,不会保存,aof对fork后的数据会通过aof_rewrite_buf缓冲区的方式追加。

因为aof是实时备份,rdb是定期备份,期限就是每次fork的那个时刻。

5.混合持久化

为解决 "RDB 加载慢" 和 "AOF 体积大" 的问题,Redis 4.0 推出 "混合持久化"------AOF 重写时,先将当前内存数据以 RDB 二进制格式写入 AOF 文件,再将重写后的新命令以 AOF 文本格式追加,形成 "RDB 头部 + AOF 尾部" 的混合文件。

配置文件里默认是开启的。

触发aof重写后,会把当前内存的状态按照 rdb的二进制格式写入新的aof中,再进行aof的写入操作。

可以看到,上面是rdb数据,下面是aof数据。

redis上同时存在aof文件和rdb快照时---》以aof为主 (aof包含的数据更全)

6.小结

Redis 的三种持久化方案各有侧重:

  • RDB 是 "定期快照",适合备份和快速加载,缺点是数据安全性低;
  • AOF 是 "实时日志",数据安全性高,缺点是加载慢、文件体积大;
  • 混合持久化结合两者优势,是当前生产环境的最优选择。

实际使用中,需根据 "数据重要性""性能要求""备份策略" 综合选择 ------ 核心是 "不盲目追求高安全性而牺牲性能,也不忽视数据安全仅追求速度",找到适合业务的平衡点。

相关推荐
z晨晨3 小时前
互联网大厂Java求职面试实战:Spring Boot与微服务场景深度解析
java·spring boot·redis·微服务·kafka·spring security·电商
老朋友此林3 小时前
一文快速入门 MongoDB 、MongoDB 8.2 下载安装、增删改查操作、索引、SpringBoot整合 Spring Data MongoDB
数据库·mongodb·springboot
炬火初现4 小时前
SQL——子查询
数据库·sql
semantist@语校4 小时前
语校网500所里程碑:日本语言学校数据库的标准化与可追溯机制
大数据·数据库·人工智能·百度·语言模型·oracle·github
野犬寒鸦4 小时前
从零起步学习Redis || 第五章:利用Redis构造分布式全局唯一ID
java·服务器·数据库·redis·分布式·后端·缓存
yenggd4 小时前
QoS之流量整形配置方法
网络·数据库·华为
陪你在童年5 小时前
EXCEL根据类别分页预览或者直接生成PDF
数据库
l1t5 小时前
在duckdb 1.4中编译和使用postgresql协议插件duckdb-pgwire
开发语言·数据库·c++·postgresql·插件·duckdb
武子康5 小时前
Java-138 深入浅出 MySQL Spring Boot 事务传播机制全解析:从 REQUIRED 到 NESTED 的实战详解 传播机制原理
java·大数据·数据库·spring boot·sql·mysql·事务