【Redis 系列】持久化特性

🚀 欢迎来到我的CSDN博客:Optimistic _ chen

一名热爱技术与分享的全栈开发者,在这里记录成长,专注分享编程技术与实战经验,助力你的技术成长之路,与你共同进步!


🚀我的专栏推荐

专栏 内容特色 适合人群
🔥C语言从入门到精通 系统讲解基础语法、指针、内存管理、项目实战 零基础新手、考研党、复习
🔥Java基础语法 系统解释了基础语法、类与对象、继承 Java初学者
🔥Java核心技术 面向对象、集合框架、多线程、网络编程、新特性解析 有一定语法基础的开发者
🔥Java EE 进阶实战 Servlet、JSP、SpringBoot、MyBatis、项目案例拆解 想快速入门Java Web开发的同学
🔥Java数据结构与算法 图解数据结构、LeetCode刷题解析、大厂面试算法题 面试备战、算法爱好者、计算机专业学生
🔥Redis系列 从数据类型到核心特性解析 项目必备

🚀我的承诺:

✅ 文章配套代码:每篇技术文章都提供完整的可运行代码示例

✅ 持续更新:专栏内容定期更新,紧跟技术趋势

✅ 答疑交流:欢迎在文章评论区留言讨论,我会及时回复(支持互粉)


🚀 关注我,解锁更多技术干货!
⏳ 每天进步一点点,未来惊艳所有人!✍️ 持续更新中,记得⭐收藏关注⭐不迷路 ✨

📌 标签:#技术博客#编程学习#Java#C语言#算法#程序员

文章目录

持久化

Redsi作为一个内存数据库,是把数据存储到内存中,这也是为什么它比其他类型的数据库更快的原因;但是我们不仅要速度快还要数据在内存上,还要数据持久,得想办法存储到硬盘上,避免不可抗力(断电)导致内存数据丢失。

所以为了数据持久化,就需要把这个数据同时写入内存和硬盘,当查询某个数据的时候,先去内存查找,找不到再到Redis数据库中查找。硬盘的数据只是在redis重启后用来恢复内存中数据的。

持久化功能有效地避免因进程退出造成数据丢失问题,当下次重启时利⽤之前持久化的⽂件即可实现数据恢复。Redis实现持久化的两个策略分别是RDB、AOF,接下来我们详细了解这两种策略。

RDB

RDB(Redis DataBase):把当前进程数据生成快照保存到硬盘。也就是定期把Redis内存中数据生成"快照",都写给硬盘。

触发RDB持久化过程分为两种:手动触发和自动触发

手动触发

程序员通过redis客户端执行手动特定命令,来触发快照生成。

  • save命令 :阻塞当前redis服务器,直到RDB过程完成,对于内存较大的情况基本不采用
  • bgsave命令 :redis进程执行fork操作创建子进程,RDB持久化过程由子进程负责,完成后自动结束,阻塞只发生在fork阶段,时间很短。redis内部大部分采取这种方式

自动触发

  • 使⽤save配置。如" savemn "表⽰m秒内数据集发⽣了n次修改,就⾃动触发RDB持久化。
  • 从节点进行全量复制操作时,主节点自动进行RDB持久化,随后将RDB文件内容发送给从节点
  • 执行shutdown命令关闭redis时,进行RDB持久化

redis是使用bgsave后台异步生成RDB快照文件,它不会阻塞主进程处理客户端请求。

  1. 当执行bgsave命令时,redis主进程会准备进行RDB持久化操作
  2. 主进程调用fork()系统调用,创建一个子进程,子进程复制主进程的内存数据;主进程在 fork 之后立即返回,继续处理客户端请求,不受子进程影响
  3. 子进程负责将当前内存中的数据快照写入到一个临时的 RDB 文件中,写完后,用临时文件代替就的RDB文件
  4. 子进程完成 RDB 文件写入后,会向父进程发送一个信号,通知主进程 RDB 操作已完成。
  5. 父进程在收到子进程完成信号后,更新持久化状态信息,等待下一次持久化

处理RDB文件

redis生成的RDB文件是存放在redis的工作目录(/var/lib/redis/)中,dump.rdb是rdb机制生成的镜像文件;它是一个二进制文件,redis把内存中的数据以压缩的形式保存到这个二进制文件中;如果rdb文件有损坏,后续redis重启可能数据会加载失败。

当生成rdb镜像的时候,生成的快照数据会保存到临时文件中,然后把之前的rdb文件删除,新的临时文件名修改为dump.rdb。

总结:

  • rdb作为一个二进制文件,代表Redis在某个时间点上的数据快照。⾮常适⽤于备份,全量复制等场景
  • redis加载RDB恢复数据远快于AOF
  • RDB⽅式数据没办法做到实时持久化,因为执行fork操作属于重量级,内存成本太高

AOF

AOF(Append Only File)持久化:以独⽴⽇志的⽅式记录每次写命令,重启时再重新执⾏AOF⽂件中的命令达到恢复数据的⽬的。

AOF的主要作⽤是解决了数据持久化的实时性 ,⽬前已经是Redis 持久化的主流⽅式

开启AOF功能需要设置配置:appendonlyyes,默认不开启;appendfilename 文件名"appendonly.aof";所在位置和rdb目录一样(/var/lib/redis),它的工作流程:

  1. 所以写入的命令都追加到AOF缓冲区中
  2. AOF缓冲区按照一定策略向硬盘做同步操作
  3. 随着AOF文件越来越大,定期对AOF文件进行重写,进行压缩
  4. 当redis服务器启动时,加载AOF文件进行数据恢复

命令写入

AOF命令写入的内容直接是文本协议格式,遵守redis格式协议,并且文本协议具有较好的兼容性、具备可读性

因为Redis使⽤单线程响应命令,如果命令每次写入AOF后直接同步到硬盘,那么内存读写的速度一定会降低,先写入缓冲区积累一定量后再同步到硬盘比较合理。

文件同步

主要介绍缓冲区同步文件的策略,由参数appendfsync配置

可配置值 介绍
always 命令写入缓冲区后直接调用fsync同步
everysec 命令写入缓冲区后只进行write操作,不调用fsync;每秒由同步线程进⾏fsync
no 命令写入缓冲区后只进行write操作,不调用fsync;由操作系统进⾏fsync
  • write操作会触发延迟写机制,Linux在内核提供**⻚缓冲区**⽤来提高硬盘IO性能。write操作在写⼊系统缓冲区后⽴即返回,同步硬盘操作依赖于系统调度机制。如果同步⽂件之前,如果此时系统故障宕机,缓冲区内数据将丢失!!!
  • fsync针对单个⽂件操作,做强制硬盘同步,fsync将阻塞直到数据写⼊到硬盘

总结:当配置为always时,每次写入都会同步AOF文件,这会显著降低性能;若设为no,虽然性能有所提升,但由于操作系统同步策略不可控,数据丢失风险会大幅增加;默认推荐的everysec配置则实现了性能与数据安全性的平衡,理论上最多只会丢失1秒内的数据。

重写机制

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

但是为什么重写后的AOF文件就变小了?

  • 进程内过期的数据不会重写
  • 旧的AOF中的⽆效命令,例如del、hdel、srem等重写后将会删除,只保留最终版本
  • 多条写操作可以合并

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

  • 手动触发:自动重写失败后或者迁移备份数据之前,程序员自己调⽤bgrewriteaof命令
  • 自动触发:满足auto-aof-rewrite-min-sizeauto-aof-rewrite-percentage两个参数后,确认触发自动重写机制

auto-aof-rewrite-min-size表⽰触发重写时AOF的最⼩⽂件⼤⼩,默认为64MB
auto-aof-rewrite-percentage代表当前AOF占⽤⼤⼩相⽐较上次重写时增加的⽐例

优化后的重写流程:

  1. 当前正在进行AOF重写,则跳过本次请求 ;若正在进行bgsave操作,则将重写命令延迟至bgsave完成后执行
  2. 主进程通过fork操作创建子进程
  3. fork完成后,主进程继续处理其他命令 ;子进程仅保留fork前的内存信息,主进程需将后续修改操作写入AOF重写缓冲区,确保命令正确记录
  4. 子进程基于内存快照,将命令合并至新的AOF文件
  5. 子进程完成重写后向主进程发送信号;主进程将缓冲区命令追加到新AOF文件,并替换原有AOF文件

redis根据持久化文件进行数据恢复

总结:

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

完结撒花!🎉

如果这篇博客对你有帮助,不妨点个赞支持一下吧!👍
你的鼓励是我创作的最大动力~

想获取更多干货? 欢迎关注我的专栏 → optimistic_chen

📌 收藏本文,下次需要时不迷路!

我们下期再见!💫 持续更新中......


悄悄说:点击主页有更多精彩内容哦~ 😊

相关推荐
食咗未18 小时前
Linux tcpdump工具的使用
linux·服务器·网络·驱动开发·tcp/ip·测试工具·tcpdump
Coder码匠18 小时前
从项目实践中学习 Spring 事务范围优化
数据库·spring
论迹18 小时前
RabbitMQ
分布式·rabbitmq
YJlio18 小时前
WinObj 学习笔记(15.7):看懂内核对象管理器与命名空间的“地图”
linux·服务器·网络·windows·笔记·学习·微信
Java 码农18 小时前
RabbitMQ集群部署方案及配置指南08--电商业务延迟队列定制化方案
大数据·分布式·rabbitmq
xingzhemengyou118 小时前
Linux lastlog查询和显示所有用户最近一次登录信息
linux·服务器
我的golang之路果然有问题18 小时前
linux 个人笔记导出之网络,防火墙,定时,权限,后台
linux·运维·服务器·网络·笔记·个人笔记
Sapphire~18 小时前
odoo-087 安装 npm (node ok npm not)
linux·运维·npm