一篇解决Redis:持久化机制

目录

认识持久化

持久化方案

RDB(Redis DataBase)

手动触发

自动触发

小结

AOF(Append-Only File)

AOF缓冲区刷新机制

AOF重写机制

AOF重写流程

​编辑

混合持久化


认识持久化

我们都知道Mysql有四大特征,原子性,持久性,隔离性,一致性。其中持久性就是因为mysql会把数据存到硬盘中,即使计算机掉电数据也不会丢失。如果把数据存储到内存中,那么就是不持久的了。而我们的redis刚好就是这样,所以要想让redis持久化,就要想办法把redis的数据存储到硬盘上。

但是redis的一个很重要的特点就是效率高,而效率高又离不开将数据存储到内存,所以该怎么办呢?答案就是‘我全都要’,将数据同时存储在内存和硬盘中,当重新打开机器后只需要从硬盘中把数据读取到内存即可,这样既保证了效率右让redis可以持久化储存数据,不过这样的方法必然会付出更大的硬盘资源。 

持久化方案

redis提供的持久化方式主要有两种RDB和AOF

RDB(定期备份):redis会定期将内存里的所有数据都写入硬盘中,并生成一个快照。

AOF:redis会将每个写操作记录下来当重启后会将这些操作自动再执行一遍

RDB(Redis DataBase)

 redis会定期将内存里的所有数据都写入硬盘中,并生成一个快照。这个快照就类似于一张照片,将这一时刻的数据和状态以文件的形式写到硬盘上

这个定期又分为两种方式手动触发和自动触发

手动触发

程序员通过特定的命令来手动触发快照

  • save:当redis执行save操作时,就会全力以赴的进行快照生成,也就会阻塞其他redis的客户端命令,就可能会使redis直接阻塞(一般不建议使用)
  • bgsave(background save):这个操作的效果和save一样,但是不会阻塞其他命令,因为此处redis采取了多进程的方式,会单独生成一个子进程来完成快照生成的操作,而父进程则继续处理客户端的请求

bgsave的执行过程

  1. 首先判定当前是否还存在其他的子进程,如果已经在执行一个bgsave命令的话,这个bgsave就会直接返回,保证只有一个子进程
  2. 如果没有其他子进程,就会通过fork操作创建出一个子进程来
  3. 子进程复制写文件,生成快照的过程,而父进程则是继续接受客户端请求
  4. 最后zjc完成持久化后,会通知父进程,父进程更新一些统计信息后,子进程就可以销毁了

//fork是linux提供的创建子进程的api,如果在其他系统上则行不通,fork会直接将父进程克隆一份,包括pcd,内存中的数据,文件描述符表等等,所以克隆出来的子进程就和父进程是完全一样的,此时就可以让父进程继续处理客户端请求,让子进程去进行持久化操作,因为内存数据完全一样,所以将子进程持久化就相当于持久化了父进程。而克隆完后的两个进程是互相独立,互不干扰的。

但是你会不会有疑问,完全拷贝下来如果有100G的内存那么开销岂不是很大?实际上,redis这里并不是直接无脑的拷贝,而是利用’写时拷贝‘,也就是如果子进程和父进程的内存数据完全一样,那么这两个进程共用一份内存,也就是不会触发真正的拷贝操作,只是在效果上像是两份,当有一方对内存数据进行了修改才会触发真正的拷贝操作,比如当fork拷贝进程时父进程来了一条指令对数据进行了修改,那么就会将数据拷贝到子进程。

举个例子假如父进程有一个int i = 1;那么子进程并不会拷贝而是和父进程共用这个数据的内存地址,如果在拷贝的过程中父进程发生了修改变成了int i = 2;那么fork就会触发真正的拷贝,将原来的int i = 1复制到一个新的内存空间,而原来的则被修改为int i = 2。(一般整个持久化过程很快,父进程不会有很多数据发生改变)

这样既不会有很大的开销,也让这两个进程可以互相独立。

当子进程写入数据时会把数据写入redis的工作目录里的dump.rdb文件,这个文件是rdb机制生成的镜像文件,而且只一个二进制的文件无法用一般的文本编辑器查看,当写入完成后就会把新的rdb文件替换旧的rdb文件。如果是save则不会触发文件替换而是直接在当前进程中往刚才的文件中写入数据

具体过程是当执行rdb镜像操作时,会把要生成的快照数据,先保存到一个临时文件中,当快照整成完毕后,再删除之前的rdb文件,把新生成的临时的rdb文件名字改成刚才的dump.rdb文件

自动触发

RDB会在Redi数据发生修改时自动保存快照进行持久化操作,不过生成一次rdb快照是一次成本比较大的操作,所以肯定不能每次修改都生成一次快照。redis是根据配置文件中的save选项来决定什么时候自动触发持久化操作的,当达到选项中的条件后redis就会自动进行快照生成

解释:

save选项有三个,分别是

  • 距离上次更新超过了900秒在这段时间内进行1次修改操作后进行自动触发
  • 距离上次更新超过了300秒在这段时间内进行10次修改操作后进行自动触发
  • 距离上次更新超过了60秒在这段时间内进行10000次修改操作后进行自动触发

//如果给save设置成' ',就代表取消自动触发

从选项中可以看到,最快的生成快照的时间是60秒,换句话说redis每两次快照之间的最短时间是60秒,假如现在完成一次快照生成,此时快照和内存的数据是一样的,但是redis突然进行了大量的修改,不过时间还没到60秒,如果这时redis突然挂了或者机器掉电,那么在这段时间内的数据因为还没来得及进行持久化操作就会直接丢失掉

//如果是通过正常流程重新启动redis服务器,此时redis服务器会在退出的时候自动触发生成rdb操作,但是如果是异常重启(kill-9或者服务器掉电)此时服务器来不及生成rdb,内存中尚未保存到快照中的数据就会随着重启丢失

小结

  • RDB是一个紧凑的二进制文件,代表redis某一个时间点上的数据快照,非常适用于备份,全量复制等场景。比如固定时间执行bgsave,并把RDB文件复制到远程机器或者文件中用于灾难恢复
  • redis加载RDB文件的速度比AOF的方式快,因为RDB使用的是二进制的方式组织数据,可以直接把数据读到内存中,按照字节的格式取出来,而AOF则是使用文本的方式。
  • RDB没法做到实时持久化,因为redis每次都要执行fork创建子进程,开销较大,也因此RDB可能会有数据丢失的风险,当数据来没来得及持久化redis就挂掉或者掉电,这部分数据就会丢失

AOF(Append-Only File)

AOF是Redis的一种替代的、完全持久化的策略。AOF机制的作用是,每当redis客户端执行写操作时,都会被记录再aof文件里通过特殊符号区分,如果发生服务器挂掉或者掉电后重启,redis就可以通过将这些命令再执行一遍而达到恢复数据的效果。

AOF的启动需要在配置文件里将appendonly.aof选项改成yes默认情况下是no,而且当启动aof机制时rdb机制是关闭的

AOF缓冲区刷新机制

引入AOF之后,redis既要写内存,又要写硬盘会不会影响效率?

AOF并不会对效率有太大的影响,实际上AOF机制并不是直接将数据写入硬盘,而是先写入内存中的一个缓冲区,积累了一定量的数据后再一次性写入硬盘,这样做就大大降低了redis写硬盘的次数(写硬盘的次数要比一次写多少数据对效率的影响大得多)。而且AOF是把每次的操作写在文件的末尾是顺序写入,要比随机写入快得多。

虽然通过刚刚的方法大大提高了AOF的效率,但是同时也带来了一个问题,缓冲区说到底还是在内存中,如果AOF正在将指令写入缓冲区时,redis挂掉或者掉电,那么此时缓冲区中的数据还没来得及写入硬盘中,也就全部丢失掉了。虽然缓冲区的方法可以提高效率,但是相应的也会来带来一些数据可靠性的问题,所谓鱼和熊掌不可兼得。

Redis提供了多种AOF缓冲区刷新策略,由参数appedfsync控制,可配置项如下:

  • always:每写入一个命令到缓冲区,就放入硬盘,刷新缓冲区的频率最高,数据可靠性最高,性能最低
  • everysec(默认):每秒清理一次缓冲区,刷新缓冲区频率低一些,数据可靠性也降低,性能相应的也提高了
  • no:redis不进行刷新缓冲区,由操作系统自行刷新,刷新频率最低,数据可靠性最低,性能最高

AOF重写机制

随着我们的服务器一直运行,aof文件也会越来越大,虽然这个文件大小对aof效率没有什么影响,但是会影响redis的开机速度,redis启动就会读取这个文件里记录的指令操作如果文件较大,执行的操作就变多,启动之间也就变长。虽然aof文件变大是不可避免的,但是这个文件里会有很多多余的内容。比如

如果redis客户端执行指令,lpush key aaa,lpush key bbb,lpush key ccc,就相当于只执行了lpush key aaa bbb ccc。再或者一些数据插入后又删除,这样的操作对于结果显然是没用的,而redis启动时却会执行一遍,也就拖长了启动时间。所以实际上我们的aof不在乎中间过程,只在乎最终的数据结果

所以aof就针对上面问题做出了应对,也就是重写机制,可以将aof中一些多余的操作指令给剔除掉,并且合并一些操作,从而缩小aof文件。

重写机制的触发方式也分为手动触发和自动触发

  • 手动触发:调用bgrewriteaof命令redis就会对文件进行重写
  • 自动触发:根据auto-aof-rewrite-min-size和auto-aof-rewrite-percentage的参数决定触发时机,auto-aof-rewrite-min-size表示触发重写时AOF的最小文件大小(默认是64mb)。auto-aof-rewrite-percentage代表AOF占用大小相比上次重写时增加的比例。

AOF重写流程

aof重写的方法和rdb很像,也是先fork一个子进程,子进程负责AOF文件的重写父进程依旧继续负责处理redis客户端的命令。但是我们重写的时候并不关心当前aof文件里都有啥,而只在乎内存中的数据状态,子进程只需要获取当前内存中的数据,然后以aof的形式写入一个新的aof文件,然后替换掉旧的文件即可。

这里的方法和RDB的快照也挺像,都是记录当前时间点的内存状态。只不过RDB是以二进制的形式,而AOF是以文本形式。

在fork创建子进程的一瞬间,子进程就继承了父进程当前的内存状态,但是重写也要一定时间,可能在重写的时候redis客户端会对内存进行一些修改

换句话说,我们的子进程记录的是fork之前的内存,但是fork之后的数据并不会丢失,父进程会再准备一个缓冲区aof_rewrite_buf当创建完子进程后,父进程就会将一些aof数据先存储到这个缓冲区。

子进程完成重写后会通知父进程,然后父进程再将aof_rewrite_buf中的数据写入新的aof文件,最后再让新的aof文件代替旧的aof文件

假如在redis正在重写的时候,又来了一个重写操作会怎么样? 

答案是,新的重写操作会直接返回不执行,而且如果在要进行AOF操作时发现redis正在进行RDB快照操作,那么aof将会阻塞等待,等到RDB操作完成后再启动AOF操作。

父进程在重写的时候依然维护写入旧的aof文件是否有必要?

 答案是,有必要因为假如redis在进行重写操作时,这时redis服务器挂掉了的话,新的aof文件还没有写入完全,缓冲区里的数据也都丢失,如果旧的aof文件再被销毁的话就会造成一部分数据的丢失。

混合持久化

虽然aof是以文本方式写入,但是当我们查看aof文件时会发现这里是用二进制存储,这是因为aof原本按照文本方式写入文件但是这样的成本较高,于是redis就引入混合持久化,也就是同时结合了rdb和aof。

按照aof的方式每个请求操作都写入文件,触发aof重写后,就会把当前内存状态按照rdb的二进制格式写入到新的aof文件中,后续在进行的操作还是按照aof文本的方式追加到文件后面。

混合持久化在配置文件里默认开启,当同时存在aof文件和rdb快照时,则以aof为主

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/bicheng/80997.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

从 Vue3 回望 Vue2:事件总线的前世今生

从 Vue3 回望 Vue2:事件总线的前世今生 以 Vue3 开发者视角回顾 Vue2 中事件总线机制 的文章。文章将围绕事件总线的缘起、用法、局限与演进展开,帮助 Vue3 开发者理解 Vue2 通信方式的历史意义及现代替代方案。 一、前言:Vue3 时代&#xff…

CSS结构性伪类、UI伪类与动态伪类全解析:从文档结构到交互状态的精准选择

一、结构性伪类选择器:文档树中的位置导航器 结构性伪类选择器是CSS中基于元素在HTML文档树中的层级关系、位置索引或结构特征进行匹配的一类选择器。它们无需依赖具体的类名或ID,仅通过文档结构即可精准定位元素,是实现响应式布局和复杂文档…

【SSL证书系列】SSL证书工作原理解读

SSL(Secure Sockets Layer)及其继任者TLS(Transport Layer Security)是用于保护网络通信安全的加密协议。SSL证书是实现HTTPS协议的核心,其工作原理涉及加密技术、身份验证和信任机制。以下是其工作原理的详细分步解析…

第二十四天打卡

import os os.getcwd() os.listdir() path_a r"C:\Users\renshuaicheng\Documents" path_b "MyProjectData" file "results.csv" file_path os.path.join(path_a,path_b,file) file_path import osstart_directory os.getcwd() # 假设这个目…

【CUDA】Sgemm单精度矩阵乘法(下)

目录 前言1. 优化技巧5:使用register模拟二级缓存(内积转外积)2. 优化技巧6:使用register模拟二级缓存 float43. 优化技巧7:global memory转置再存放shared memory4. 优化技巧8:使用double buffer加速矩阵…

【1000以内具有12个以上因子的整数并输出它的因子】2021-12-27

缘由c语言输入1000以内具有12个以上因子的整数 并输出它的因子-编程语言-CSDN问答 int 求因子个数(int 数, int* 因子 { 0 }) {//缘由https://bbs.csdn.net/topics/399168406int 和 0, 求 1, 商 0, 含 0;//因子不含1和数本身while (求 < (商 数 / 求))if (!(数 % 求)…

C#中的dynamic与var:看似相似却迥然不同

在C#编程的世界里&#xff0c;var和dynamic这两个关键字常常让初学者感到困惑。它们看起来都在定义变量时省略了显式类型声明&#xff0c;但实际上它们的工作方式和应用场景有着天壤之别。今天&#xff0c;让我们一起揭开这两个关键字的神秘面纱。 var&#xff1a;编译时的类型…

流速仪数据处理及流量断面线绘制

1 需求描述 在实际航道测量项目中&#xff0c;有测量断面线流量流速的需求&#xff0c;得使用流速仪在现场进行测量&#xff0c;相关操作在之前已经写了记录。本次手册记录后期数据处理与流量线绘制&#xff0c;以该区域为例。 流速仪设备操作说明 2 规范要求 3 流量断面表格…

购物车构件示例

通用购物车构件设计 注:代码仅用于演示原理,不可用于生产环境。 一、设计目标 设计一个高度可复用的购物车构件,具备以下特点: 与具体业务系统解耦支持多种应用场景(商城、积分系统等)提供标准化接口易于集成和扩展二、核心架构设计 1. 分层架构 ┌─────────…

数据结构·字典树

字典树trie 顾名思义&#xff0c;在一个字符串的集合里查询某个字符串是否存在树形结构。 树存储方式上用的是结构体数组&#xff0c;类似满二叉树的形式。 模板 定义结构体和trie 结构体必须的内容&#xff1a;当前结点的字符&#xff0c;孩子数组可选&#xff1a;end用于查…

ES面试题系列「一」

1、Elasticsearch 是什么&#xff1f;它与传统数据库有什么区别&#xff1f; 答案&#xff1a;Elasticsearch 是一个基于 Lucene 的分布式、开源的搜索和分析引擎&#xff0c;主要用于处理大量的文本数据&#xff0c;提供快速的搜索和分析功能。与传统数据库相比&#xff0c;E…

2025年6月一区SCI-不实野燕麦优化算法Animated Oat Optimization-附Matlab免费代码

引言 近年来&#xff0c;在合理框架内求解优化问题的元启发式算法的发展引起了全球科学界的极大关注。本期介绍一种新的元启发式算法——不实野燕麦优化算法Animated Oat Optimization algorithm&#xff0c;AOO。该算法模拟了不实野燕麦的3种独特行为&#xff0c;于2025年6月…

Agent Builder API - Agent Smith 扩展的后端服务(开源代码)

​一、软件介绍 文末提供程序和源码下载 Agent Builder API - Agent Smith 扩展的后端服务&#xff08;开源代码&#xff09;手动设置&#xff1a;在本地计算机中克隆此存储库并启动 python FAST API 服务器。&#xff08;可选&#xff09;安装并设置 Mongo DB。Dev Container…

C及C++的SOAP协议库

一.gSOAP gSOAP 是一个功能强大的开源工具包&#xff0c;专为 C 和 C 设计&#xff0c;用于快速开发基于 SOAP 协议的 Web 服务和客户端。 1.协议支持 SOAP 版本&#xff1a;完整支持 SOAP 1.1/1.2 规范&#xff0c;包括消息格式、编码规则和错误处理。 传输协议&#xff1a…

html5+css3实现傅里叶变换的动态展示效果(仅供参考)

<!DOCTYPE html> <html lang"zh-CN"> <head><meta charset"UTF-8"><meta name"viewport" content"widthdevice-width, initial-scale1.0"><title>傅里叶变换的动态展示效果</title><sty…

ECharts中Map(地图)样式配置、渐变色生成

前言 在日常开发中&#xff0c;ECharts 几乎成了我们绘制数据图表的标配工具&#xff0c;功能强大到几乎无所不能。不过每次用的时候都要翻官方文档查配置项&#xff0c;确实有点小繁琐 &#x1f605; 为了提升效率&#xff0c;也方便以后快速复用&#xff0c;这里就整理记录…

内存分配器ptmalloc2、tcmalloc、jemalloc,结构设计、内存分配过程详解

1. 引言 博主之前做过一个高并发内存池的项目实践&#xff0c;在实践中对于内存分配器的内存分配过程理解更加深刻了。在此期间&#xff0c;翻查了不少资料以及博客&#xff0c;发现源码分享的博客不多&#xff0c;能生动完整的讲述ptmalloc2、tcmalloc、jemalloc它们的结构设…

【拥抱AI】Deer-Flow字节跳动开源的多智能体深度研究框架

最近发现一款可以对标甚至可能超越GPT-Researcher的AI深度研究应用&#xff0c;Deer-Flow&#xff08;Deep Exploration and Efficient Research Flow&#xff09;作为字节跳动近期开源的重量级项目&#xff0c;正以其模块化、灵活性和人机协同能力引发广泛关注。该项目基于 La…

openfeign与dubbo调用下载excel实践

一、前言 openfeign和dubbo均是rpc框架 RPC&#xff08;Remote Procedure Call&#xff0c;远程过程调用&#xff09;框架 是一种允许程序像调用本地方法一样调用远程服务器上函数的技术。它隐藏了底层网络通信的复杂性&#xff0c;让开发者可以专注于业务逻辑&#xff0c;实现…

解密企业级大模型智能体Agentic AI 关键技术:MCP、A2A、Reasoning LLMs-强化学习算法

解密企业级大模型智能体Agentic AI 关键技术&#xff1a;MCP、A2A、Reasoning LLMs-强化学习算法 现在我们的核心问题是有一些同学会知道要才能强化学习。为什么才能强化学习&#xff1f;是实现AGI。例如从这个其实你从第一阶段开始以后&#xff0c;就是chatbot&#xff0c;这…