当前位置: 首页 > news >正文

Redis:持久化

🌈 个人主页:Zfox_
🔥 系列专栏:Redis

🔥 认识持久化

所谓持久化,就是能够把数据存储在硬盘上,这本身就是持久化,当数据存储在硬盘之后,当重启进程或是主机之后,数据也依旧存在

而我们知道Redis本身其实是一个内存级别的数据库,那这就意味着它本身其实是不能持久化的,要想让Redis实现持久化,就必须让Redis把数据写到硬盘上

那怎么写呢?

当现在要插入一个新的数据的时候,就需要把这个数据同时存储到磁盘和内存当中,而当查询某个具体的数据的时候,却还是依旧直接从内存中进行读取,硬盘中的数据,只是为了在Redis进行重启的时候可以来恢复到内存中的数据的

这样做是有代价的,同样的数据在硬盘和内存中都会进行存储,不过考虑到硬盘本身的成本其实并不高,因此也不过多讲究

🔥 持久化策略

Redis⽀持RDB和AOF两种持久化机制,持久化功能有效地避免因进程退出造成数据丢失问题,当下次重启时利⽤之前持久化的⽂件即可实现数据恢复。本章内容:

  • 介绍RDB、AOF的配置和运⾏流程,以及控制持久化的命令, 如bgsave和bgrewriteaof。
  • 对常⻅持久化问题进⾏分析定位和优化
  1. RDB:全称是 Redis Database
  2. AOF:全称是 Append Only File

下面先说一下这两个持久化方式的区别:

对于 RDB 来说,其实就是一种定期备份,每隔一段时间就对于数据进行存储,而对于 AOF 来说,是实时备份

🔥 RDB

RDB 会定期的把 Redis 在内存的数据写入到硬盘中,就生成了一个快照,后续如果 Redis 重启了,也不用过多担心,可以根据之前的快照信息把数据存储起来进行恢复

那这个定期该如何进行掌控呢?

🦋 触发机制

🎀 手动触发

程序员可以手动的进行存储快照,例如可以通过两个命令,save 或者是 bgsave 进行存储到本地

  • save:在执行 save 命令的时候,Redis 会全力以赴的进行存储快照,这就意味着 Redis 会阻塞掉其他的请求,类似于之前说到的 keys * 的问题

  • bgsave:而对于 bgsave 来说,就解决了这个问题,而解决的方法其实采取的是使用了多进程的方式来进行解决的(Redis进程执⾏fork操作创建⼦进程,RDB持久化过程由⼦进程负责,完成后⾃动结束。阻塞只发⽣在fork阶段)

图4-1bgsave命令的运作流程

在这里插入图片描述

  1. 执⾏bgsave命令,Redis⽗进程判断当前进是否存在其他正在执⾏的⼦进程,如RDB/AOF⼦进程,如果存在bgsave命令直接返回。
  2. ⽗进程执⾏fork创建⼦进程,fork过程中⽗进程会阻塞,通过infostats命令查看latest_fork_usec选项,可以获取最近⼀次fork操作的耗时,单位为微秒。
  3. ⽗进程fork完成后,bgsave命令返回"Backgroundsavingstarted"信息并不再阻塞⽗进程,可以继续响应其他命令。
  4. ⼦进程创建RDB⽂件,根据⽗进程内存⽣成临时快照⽂件,完成后对原有⽂件进⾏原⼦替换。执⾏lastsave命令可以获取最后⼀次⽣成RDB的时间,对应info统计的rdb_last_save_time选项。
  5. 进程发送信号给⽗进程表⽰完成,⽗进程更新统计信息。

🎀 自动触发

在 Redis 的配置文件中,就可以进行合适的设置,让 Redis 每隔一段时间就进行存储

Redis 生成的 RDB 文件,所在的位置是在 Redis 的工作目录当中的,这也是在 Redis 的配置文件中进行设置的

🦋 RDB 的特性

对于 RDB 来说,它并不是随时都会进行更新的,而是需要一定的触发时机,下面在配置文件中进行观察:

在这里插入图片描述

在这个配置文件中,可以看到当前 Redis 的持久化策略是,900 秒内改变1次就进行缓存,300 秒内改变 10 次,60 秒内改变 10000 次…以此类推

🦋 RDB⽂件的处理

  • 保存:RDB⽂件保存再dir配置指定的⽬录(默认/var/lib/redis/ )下,⽂件名通过dbfilename配置( 默认dump.rdb )指定。可以通过执⾏configsetdir{newDir}和configsetdbfilename{newFilename}运⾏期间动态执⾏,当下次运⾏时RDB⽂件会保存到新⽬录。
  • 压缩:Redis默认采⽤LZF算法对⽣成的RDB⽂件做压缩处理,压缩后的⽂件远远⼩于内存⼤⼩,默认开启,可以通过参数configsetrdbcompression{yes|no}动态修改。

在这里插入图片描述

  • 校验:如果Redis启动时加载到损坏的RDB⽂件会拒绝启动。这时可以使⽤Redis提供的redischeck-dump⼯具检测RDB⽂件并获取对应的错误报告。

🦋 RDB的优缺点

  • RDB是⼀个紧凑压缩的⼆进制⽂件,代表Redis在某个时间点上的数据快照。⾮常适⽤于备份,全量复制等场景。⽐如每6⼩时执⾏bgsave备份,并把RDB⽂件复制到远程机器或者⽂件系统中(如hdfs)⽤于灾备。
  • Redis加载RDB恢复数据远远快于AOF的⽅式。
  • RDB⽅式数据没办法做到 实时持久化/秒级持久化 。因为bgsave每次运⾏都要执⾏fork创建⼦进程,属于重量级操作,频繁执⾏成本过⾼。
  • RDB⽂件使⽤特定⼆进制格式保存,Redis版本演进过程中有多个RDB版本,兼容性可能有⻛险。

🦋 结论

🧑‍💻 Redis 生成 RDB 快照这件事,本身是一件成本比较高的事,所以生成快照不可以太频繁,而因为生成快照不能太频繁,就意味着可能会出现快照数据和实际数据相差较大的情况

那为了解决这样的问题,就出现了 AOF 这种解决方案

🔥 AOF

AOF(AppendOnlyFile)持久化:以独⽴⽇志的⽅式记录每次写命令,重启时再重新执⾏AOF⽂件中的命令达到恢复数据的⽬的。AOF的主要作⽤是解决了数据持久化的实时性,⽬前已经是Redis持久化的主流⽅式。

AOF 作为一种解决方案,对标的是 RDB 这种解决方案,RDB 带来的问题是,不能进行实时的持久化保存数据,在两次生成快照之间,实时的数据就会因为重启而丢失

因此有了 AOF,AOF 策略有些类似于 binlog,它会把用户的每一个操作都记录在文件当中,这样当 Redis 进行重新启动的时候,就会读取这个 AOF 中的内容,来进行恢复数据

当开启 AOF 的时候,RDB 就不生效了,AOF 默认是不会开启的:
在这里插入图片描述

AOF 本质上是一个文本文件,它会把对于 Redis 的各种操作都记录到一个文件当中,来对于命令的细节进行区分

🦋 使⽤AOF

开启AOF功能需要设置配置:appendonlyyes,默认不开启。AOF⽂件名通过 appendfilename配置(默认是appendonly.aof)设置。保存⽬录同RDB持久化⽅式⼀致,通过dir 配置指定。AOF的⼯作流程操作:命令写⼊(append)、⽂件同步(sync)、⽂件重写 (rewrite)、重启加载(load),如图4-2所⽰。

图4-2AOF⼯作流程

在这里插入图片描述

  1. 所有的写⼊命令会追加到aof_buf(缓冲区)中。
  2. AOF缓冲区根据对应的策略向硬盘做同步操作。
  3. 随着AOF⽂件越来越⼤,需要定期对AOF⽂件进⾏重写,达到压缩的⽬的。
  4. 当Redis服务器启动时,可以加载AOF⽂件进⾏数据恢复。

Redis 虽然是一个单线程的服务器,但是速度依旧很快,快的原因在于只是进行操作内存,那引入AOF 后,又要进行内存操作也要进行磁盘读取,是否会影响效率?答案是否定的

AOF 的机制并非让工作线程直接进行磁盘的操作,而是把信息存储到缓冲区后,然后把信息统一写入硬盘 ,同时,AOF 写入硬盘的方法是 直接顺序进行写入,这个效率是比随机写入快的,所以从某种程度上来说也是一种解决的方式

那现在问题来了,如果在缓冲区的数据丢失了,此时 Redis 也会进行数据丢失,因此给出的解决方式是 Redis 提供了选项,可以允许程序员进行实际情况来判断缓冲区的刷新策略,频率越高,就意味着性能影响越大,数据可靠性越高,反之也是这样

🦋 ⽂件同步

Redis提供了多种AOF缓冲区同步⽂件策略,由参数appendfsync控制,不同值的含义如表4-1所⽰。

表4-1AOF缓冲区同步⽂件策略

在这里插入图片描述

系统调⽤write和fsync说明:

  • write操作会触发延迟写(delayedwrite)机制。Linux在内核提供⻚缓冲区⽤来提供硬盘IO性能。write操作在写⼊系统缓冲区后⽴即返回。同步硬盘操作依赖于系统调度机制,例如:缓冲区⻚空间写满或达到特定时间周期。同步⽂件之前,如果此时系统故障宕机,缓冲区内数据将丢失。
  • Fsync针对单个⽂件操作,做强制硬盘同步,fsync将阻塞直到数据写⼊到硬盘。
  • 配置为always时,每次写⼊都要同步AOF⽂件,性能很差,在⼀般的SATA硬盘上,只能⽀持⼤约⼏百TPS写⼊。除⾮是⾮常重要的数据,否则不建议配置。
  • 配置为no时,由于操作系统同步策略不可控,虽然提⾼了性能,但数据丢失⻛险⼤增,除⾮数据重要程度很低,⼀般不建议配置。
  • 配置为everysec,是默认配置,也是推荐配置,兼顾了数据安全性和性能。理论上最多丢失1秒的数据。

🦋 重写机制(AOF 瘦身操作)

AOF 存储的是对 Redis 的一系列操作过程,但是随着 Redis 的操作变多,这就意味着文件的存储量也会变大,所以 Redis 的内部会存在一些机制,可以让 AOF 文件进行整理,剔除其中的冗余操作,把 AOF 的文件进行瘦身

随着命令不断写⼊AOF,⽂件会越来越⼤,为了解决这个问题,Redis引⼊AOF重写机制压缩⽂件体积。AOF⽂件重写是把Redis进程内的数据转化为写命令同步到新的AOF⽂件。

重写后的AOF为什么可以变⼩?有如下原因:

  • 进程内已超时的数据不再写⼊⽂件。
  • 旧的AOF中的⽆效命令,例如del、hdel、srem等重写后将会删除,只需要保留数据的最终版本。
  • 多条写操作合并为⼀条,例如lpushlista、lpushlistb、lpushlist从可以合并为lpushlistabc。

较⼩的AOF⽂件⼀⽅⾯降低了硬盘空间占⽤,⼀⽅⾯可以提升启动Redis时数据恢复的速度。

AOF重写过程可以⼿动触发和⾃动触发:

  • ⼿动触发:调⽤bgrewriteaof命令。
  • ⾃动触发:根据auto-aof-rewrite-min-size和auto-aof-rewrite-percentage参数确定⾃动触发时机。
    • auto-aof-rewrite-min-size:表⽰触发重写时AOF的最⼩⽂件⼤⼩,默认为64MB。
    • auto-aof-rewrite-percentage:代表当前AOF占⽤⼤⼩相⽐较上次重写时增加的⽐例。

当触发AOF重写时,图4-3介绍它的运⾏流程。

图4-3AOF重写流程

在这里插入图片描述

  1. 执⾏AOF重写请求。

如果当前进程正在执⾏AOF重写,请求不执⾏。如果当前进程正在执⾏bgsave操作,重写命令延迟到bgsave完成之后再执⾏。

  1. ⽗进程执⾏fork创建⼦进程。
  2. 重写

a. 主进程fork之后,继续响应其他命令。所有修改操作写⼊AOF缓冲区并根据appendfsync策略同步到硬盘,保证旧AOF⽂件机制正确。

b. ⼦进程只有fork之前的所有内存信息,⽗进程中需要将fork之后这段时间的修改操作写⼊AOF重写缓冲区中。

  1. ⼦进程根据内存快照,将命令合并到新的AOF⽂件中。
  2. ⼦进程完成重写

a. 新⽂件写⼊后,⼦进程发送信号给⽗进程。

b. ⽗进程把AOF重写缓冲区内临时保存的命令追加到新AOF⽂件中。

c. ⽤新AOF⽂件替换⽼AOF⽂件。

在这里插入图片描述

🦋 混合持久化

在这里插入图片描述

🦋 启动时数据恢复

当Redis启动时,会根据RDB和AOF⽂件的内容,进⾏数据恢复,如图4-4所⽰。

图4-4Redis根据持久化⽂件进⾏数据恢复

在这里插入图片描述

在这里插入图片描述

本章重点回顾

  1. Redis提供了两种持久化⽅案:RDB和AOF。
  2. RDB视为内存的快照,产⽣的内容更为紧凑,占⽤空间较⼩,恢复时速度更快。但产⽣RDB的开销较⼤,不适合进⾏实时持久化,⼀般⽤于冷备和主从复制。
  3. AOF视为对修改命令保存,在恢复时需要重放命令。并且有重写机制来定期压缩AOF⽂件。
  4. RDB和AOF都使⽤fork创建⼦进程,利⽤Linux⼦进程拥有⽗进程内存快照的特点进⾏持久化,尽可能不影响主进程继续处理后续命令。

🔥 共勉

😋 以上就是我对 Redis:持久化 的理解, 觉得这篇博客对你有帮助的,可以点赞收藏关注支持一波~ 😉
在这里插入图片描述

http://www.lqws.cn/news/522613.html

相关文章:

  • dockerfile命令及构建
  • (C++)vector数组相关基础用法(C++教程)(STL库基础教程)
  • 多线程知识点
  • ffmpeg获取组播中指定视频流、音频流(通过pid、program)首发
  • 盖雅工场 2025 香港 SAP NOW 大会深度解析:AI 重构亚太劳动力管理数字化生态
  • Nginx服务部署与配置
  • DexGraspVLA:面向通用灵巧抓取的分层VLA-2025.5.22-北京大学
  • HTML表格元素
  • Spring 用的是什么动态代理?它是怎么配置的?
  • fluentd + elasticsearch + grafana 不能显示问题
  • 16.7 Prometheus+Grafana实战:容器化监控与日志聚合一站式解决方案
  • Linux远程机器无法连接-------解决方案
  • 开源代码修复新标杆——月之暗面最新开源编程模型Kimi-Dev-72B本地部署教程,自博弈修复 Bug
  • AI知识库搭建需要的开源技术方案
  • C#.Net筑基-优雅LINQ的查询艺术
  • 基于Hp感染的慢性胃炎居家管理小程序的设计与实现(消息震动)
  • 连锁企业网络互联方案对比:MPLS专线 vs 内网穿透
  • MySQL为什么默认引擎是InnoDB?
  • 永磁同步电机无速度算法--基于三角函数锁相环的滑模观测器
  • django 中间件
  • 打造丝滑的Android应用:LiveData完全教程
  • YOLOv8 改进点详解
  • 联邦学习中的本地迭代误差与全局聚合误差
  • CSMatIO库的安装与C#实现.mat文件生成
  • 数据库系统总结
  • cocos2 实现全局音量管理
  • 51c嵌入式~CAN~合集2
  • 数据文件写入技术详解:从CSV到Excel的ETL流程优化
  • 使用AkShare获取股票报表
  • [省选联考 2025] 推箱子