刷新你对Redis持久化的认知

news2025/1/14 1:11:08

认识持久化

redis是一个内存数据库,数据存储到内存中。而内存的数据是不持久的,要想做到持久化,就需要让redis把数据存储到硬盘上。
因此redis既要在内存上存储一份数据,还要在硬盘上存储一份数据。这样这两份数据在理论上是完全相同的(实际上可能存在一点差异,这取决于咱们怎么进行持久化)。当要插入一个数据的时候,需要同时写入内存和硬盘(实际上怎么写入硬盘有不同的策略);当查询某个数据的时候,直接从内存读取;硬盘的数据只是在redis重启的时候,用来恢复内存中的数据。

redis实现持久化的两种方式

  1. RDB:定期备份
  2. AOF:实时备份

RDB

RDB定期的把redis内存中所有数据,给拍个”照片“,生成快照文件写入硬盘中。一旦redis重启,就可以根据刚才的”快照“把内存的数据给恢复回来。

定期的两种方式

手动触发

程序员通过redis客服端,执行特定命令,触发快照的生成

  1. save命令,执行save时,redis会全力投入到生成“快照”中,阻塞redis其他客服端的命令。因此一般不建议使用save命令
  2. bgsave命令,并不会影响redis服务器处理其他客服端的请求和命令,通过多进程实现,如下图所示:

image.png

  1. 执行bgsave命令,父进程会判断是否存在其他正在执行的子进程,例如RDB/AOF子进程,如果存在,bgsave命令会直接返回
  2. 父进程执行fork创建子进程,fork过程中父进程会阻塞,可以通过info status命令查看 latest_fork_usec选项,获取最近一次fork操作耗时,单位ms.

fork是linux提供创建子进程的api,直接把父进程复制一份(pcb,文件描述符表,虚拟地址空间(内存中的数据)),作为子进程。在redis服务器中有若干变量,保存了一些键值对数据,随着fork的进行,子进程内存中也会存在和刚才父进程一样的变量。因此子进程进行“持久化”操作,相当于把父进程的内存数据给持久化了。(父进程打开一个文件,fork之后,子进程也同样使用这个文件;这就导致子进程进行持久化写入的那个文件和父进程本来要写的文件是同一个)
:::tips
fork的“写时拷贝”机制
:::
image.png
父进程进行一些修改
image.png
bgsave这个场景中,绝大部分内存数据是不需要改变的,因此子进程的“写时拷贝”并不会触发很多次,也就保证了整体的“拷贝时间”是可控的

  1. 父进程fork完成后,bgsave命令返回"Background saving started"信息,不再阻塞父进程,可以继续响应其他命令
  2. 子进程创建RDB文件,根据父进程内存生成临时快照文件,完成后对原有文件进行原子替换。执行lastsave命令可以获取最后一次生成RDB的时间,对应info统计的rdb_last_save_time选项。
  3. 进程发送信号给父进程表示完成,父进程更新统计信息

自动触发

在redis的配置文件redis.conf进行设置,让redis每隔多长时间,每生产多少次修改就触发.

查看redis.conf文件

image.png
上述数值可以修改配置,但是不能让rdb操作过于频繁,因为生成一次rdb快照是一个成本比较高的成本。

RDB生成的文件

redis生成的rdb文件,存放在redis的工作目录中,可以在redis.conf中查看该工作目录。
:::tips
cd /etc/
vim redis.conf
:::
image.png
切换到该工作目录
:::tips
cd /var/lib/redis/
ll
:::
image.png
其中dump.rdb即rdb机制生成的镜像文件,redis服务器默认是开启rdb的。dump.rdb是一个二进制文件,redis将内存中的数据,以压缩的形式,保存到这个二进制文件中。

redis默认采用LZF算法对生成的RDB文件做压缩处理,默认开启,可以在redis.conf文件中修改配置image.png

后续redis服务器重新启动,就会加载dump.rdb文件,在加载时会进行校验,redis提供了rdb文件的检查工具redis-check-rdb
image.png
由上图我们发现检查工具和redis服务器在5.0版本是同一个可执行程序,可以在运行的时候加入不同的选项,从而实现不同的功能。例如,运行的时候,加入rdb文件作为命令行参数,此时就是以检查工具的方式运行,不会真的启动redis服务器。
说明dump.rdb文件没有问题,解析正确

生成RDB文件的方式

  1. 手动执行bgsave触发一次生成快照

image.png
redis服务器重新启动之后,会加载rdb文件的内容,恢复内存中的数据。
dump.rdb文件如下,虽然我们看不懂二进制文件,但是能看到key1,key2,key3。
image.png

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

image.png
由上图可知,如果是通过正常流程重启redis服务器,此时redis服务器在退出的时候,会自动触发rdb操作;如果是异常重启(kill -9/服务器掉电)此时redis服务器来不及生成rdb,内存中尚未保存到快照中的数据,就会随着重启而丢失。
:::info
redis生成快照,不通过手动执行命令,而是自动触发有如下情况

  1. 满足配置文件中超过M秒,修改了N次,触发save操作

image.png

  1. 通过shutdown命令(redis正确关闭服务器的命令)也会触发
  2. redis进行主从复制的时候,主节点会自动生成rdb快照,然后把rdb快照文件内容传输给从节点
    :::

观察生成rdb的过程

bgsave通过创建子进程,让子进程完成持久化操作。持久化会把数据写入新的文件中,然后使用新的文件替换旧的文件。由于持久化速度太快(数据量小),难以观察;而新文件替换旧文件是容易观察的。
image.png
inode编号是文件的身份标识,两次inode编号不同,说明文件并不是同一个文件,只是内容相同。

linux文件系统的组织方式是ext4,主要将整个文件系统分成3个部分

  1. 超级块,存放一些管理信息
  2. inode区,存放inode节点,每个文件都会分配一个inode数据结构,包含了文件的各种元数据
  3. block区,存放文件的数据内容

RDB的优缺点

  • RDB是一个压缩的二进制文件,代表redis在某个时间点上的数据快照。非常适合用来备份,全量复制等场景。比如每6个小时执行bgsave备份,并把rdb文件复制到远程机器或者文件系统中用于备灾
  • redis加载rdb恢复数据远快于aof方式。因为rdb使用二进制的方式组织数据,直接把数据读到内存中,按照字节的格式取,放到结构体/对象中即可。而aof是使用文本的方式组织数据,则需要进行一系列的字符串切分操作
  • rdb文件使用特定二进制格式保存,当redis版本升级以后,兼容性可能存在风险。

可以遍历旧版本的redis中所有的key,把数据取出来,插入到新的redis服务器中

  • rdb最大的问题就是不能实时持久化保存数据,在两次快照之间,实时的数据可能随着重启而丢失

AOF

aof以独立日志的方式记录每次写的命令,重启时在重新执行aof文件中的命令达到恢复数据的目的。aof主要作用是解决数据持久化的实时性问题,是目前redis持久化的主流方式。

使用AOF

开启aof功能需要在配置文件中设置:appendonly yes默认不开启。当开启aof后,rdb就不生效;启动以后不再读取rdb内容。aof文件名通过appendfilename配置文件中设置。aof文件所在位置和rdb文件所在的目录一样,默认/var/lib/redis(可配置)
image.png

向redis中添加key1,key2,key3

image.png
image.png
查看appendonly.aof文件
image.png

appendonly.aof文件记录了你的每一个操作命令,通过一些特殊符号作为分割符,来对命令的细节做出区分。aof文件的格式是文本格式,因为文本协议具备更好的兼容性,事先简单,具备可读性。

AOF的工作流程

image.png

aof-buf缓冲区

引入aof机制,既写内存,有写硬盘,速度还会很快吗?

  1. aof机制并不是直接让工作线程把数据写入硬盘,而是先写入内存的缓冲区aof_buf,积累一波后,再统一写入硬盘,降低了写硬盘的次数。写硬盘的时候,一次写入硬盘数据的多少,对于性能影响不是很大,但是写入硬盘的次数影响很大。
  2. 硬盘上读写数据,顺序读写的速度比较快,随机访问的速度比较慢。而aof每次把新的操作写入到原有文件的末尾,属于顺序写入。

把数据写入缓冲区,本质还是在内存中,当进程挂了或者主机掉电,缓冲区的数据会不会丢失?

会,缓冲区中没来得及写入硬盘的数据会丢。
缓冲区的刷新策略
image.png

  • always:每一步操作立刻同步到aof文件中,频率最高,数据可靠性最高,性能最低
  • everysec:每秒将缓冲区的数据写入aof文件,频率低一些,数据可靠性降低一些,性能提高一些,默认采用everysec策略image.png
  • no:由操作系统来控制什么时候写入aof文件,频率最低,数据可靠性最低,性能最高

重写机制(rewrite)

随着操作的增多,aof文件体积越来越大。redis启动的时候需要读取aof文件内容,这就会影响到redis启动时间。实际上redis启动的时候,只关注最终结果,并不关心aof文件中记录的中间过程,所以aof文件中有一些内容存在冗余。如下所示:
image.png
因此redis就引入了“重写机制”,对aof文件进行整理操作,剔除其中的冗余操作,并且合并一些操作,达到给aof文件瘦身的效果。

触发重写机制
  1. 手动触发:执行bgrewriteaof命令
  2. 自动触发:根据auto-aof-rewrite-min-sizeauto-aof-rewirte-percentage参数确定自动触发时机
    1. auto-aof-rewrite-min-size:表示触发重写时aof的最小文件大小,默认是64Mb
    2. auto-aof-rewrite-percentage:表示当前aof占用大小相比上次重写时增加的比例

image.png

AOF重写流程

image.png

序号2和4的过程

aof重写和rdb生成快照文件一样,都是通过多进程的方式。通过fork创建子进程,父进程负责接收请求,子进程负责针对aof文件进行重写。子进程只需要把当前内存中的数据,获取出来,以aof的格式写入到一个新的aof文件中。因为内存中的数据状态,就相当于把aof文件整理后的结果。此处子进程写数据的过程,类似于rdb生成一个镜像快照。只不过rdb是按照二进制的方式生成的,aof重写则是按照aof要求的文本格式生成的,都是把当前内存的所有数据状态给记录到文件中。

序号3.1的过程

子进程写新aof文件的同时,父进程仍然在不停的接收客服端新的请求,父进程会把这些请求先写入aof_buf缓冲区中,再刷新到原有的aof文件中。

序号3.2,5.1, 5.2, 5.3过程

在创建子进程的一瞬间,子进程继承了当前父进程的内存状态。因此子进程中的内存数据是父进程fork之前的状态,fork之后,新的请求,对内存造成的修改,是子进程不知道的。此时,父进程准备了一个aof_rewrite_buf缓冲区,专门放fork之后的数据。子进程把aof数据写完以后,会通过信号通知一下父进程,父进程再把aof_rewrite_buf缓冲区的内容也写到新的aof文件中,到这就可以用新的aof文件替换旧的aof文件。
什么是信号?
信号是linux的神经系统,是进程间通信的一种手段。信号能表达的信息有限,并不像socket可以传输任意数据,图中子进程向父进程发送一个信号,表示“我已经干完了”。
信号包含3部分

  • 信号源:哪个进程发送的
  • 信号类型:例如kill -9 表示给指定进程发送9号信号
  • 信号的处理函数:接收方接到这个信号触发的行为

如果在执行bgrewriteaof时,当前redis已经正在进行aof重写,会咋样?

此时,不会再次执行aof重写,直接返回。

如果在执行bgrewriteaof时,当前redis在生成rdb文件快照,会咋样?

此时aof重写操作会等待,等待rdb快照生成完毕之后,再执行aof重写

父进程fork完成后,子进程开始写入新的aof文件,随着时间推移,子进程写完新的文件后,让新的aof文件替换旧的aof文件。此时父进程仍然继续写入旧的aof文件是否有意义?

预防极端情况,例如服务器挂了,子进程的内存数据都会丢失,新的aof文件内容不完整,所以如果父进程不坚持写入旧的aof文件,重启旧无法保证数据的完整性。

启动时恢复数据

当redis启动时,会根据rdb和aof文件的内容,进行数据恢复,如下图所示:
image.png
如果开启aof,以aof为主,忽略rdb文件。因为aof中包含的数据比rdb更全。

混合持久化

aof是按照文本的方式写入文件的,导致后续加载的成本较高。因此redis引入“混合持久化”结合了rdb和aof特点,按照aof的方式,把每个请求/操作都记录到文件中,在触发aof重写之后,就会把当前内存的状态按照rdb的二进制格式写入到新的aof文件中,后续再进行的操作,仍然按照aof文本的方式追加到文件后头。
在redis.conf配置文件中开启混合持久化
image.png
示例:
image.png
打开appendonly.aof文件
image.png

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

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

相关文章

掌握Spring框架核心组件:深入探讨IOC、AOP、MVC及注解方式面试指南【经验分享】

目录 引言 一、Spring IOC篇 1.什么是Spring 2.核心概念 3.核心架构 4.什么是控制反转(IOC) 5.依赖注入(DI) 二、Spring AOP篇 1.什么是AOP 2.Spring AOP代理机制 3.核心概念 4.通知分类 三、Spring MVC篇 1.什么…

【24考研】:四川大学计算机学院23届874考研考情分析

四川大学计算机学院23届CS考研考情分析 作者:老李 往年都是大佬们做的, 今年正好自己在做公众号这一块, 因此不自量力的承担这个工作,顺便锻炼一点pandas包和plt包的应用能力。 所以形式上我也会仿照一下往年的大佬。 21考情&a…

【Nacos】使用Nacos-Sync同步两个Nacos集群中的数据

Nacos-Sync官方文档:NacosSync 用户手册 介绍 NacosSync是一个支持多种注册中心的同步组件,基于Spring boot开发框架,数据层采用Spring Data JPA,遵循了标准的JPA访问规范,支持多种数据源存储,默认使用Hibernate实现,更加方便的支持表的自动创建更新使用了高效的事…

pg_database中的datlastsysoid

一,关于 pg_database 在 PostgreSQL 中,对于在数据库集群内创建的每个数据库,其关键信息都会被保存到 pg_database 系统表中。 PostgreSQL 确保通过 pg_database 系统表持久化存储每个数据库的属性信息,以方便后续管理和使用。这也让 pg_da…

【广州华锐互动】综合管廊3D可视化管理系统有效解决城市公用设施管理问题

在过去的几十年中,城市化进程不断加速,城市规模不断扩大,人口密度不断增加。这种发展带来了对城市基础设施的巨大需求,尤其是对电力、水、燃气和通信等公用设施的管理和维护。 为了满足这些需求,许多城市开始建设和管理…

如何实现自定义数据库账号密码加解密

背景 在实际的项目开发中我们有时候基于安全考虑需要在项目配置文件中对数据库账号密码做加密处理,这个时候我们就可以使用jasypt这个组件来实现。如果有些项目安全等级要求比较高,可能加密的算法需要自定义或者使用SM4国密算法来实现加解密&#xff0c…

【人工智能】—_逻辑回归分类、对数几率、决策边界、似然估计、梯度下降

文章目录 逻辑回归分类Logistic Regression ClassificationLogistic Regression: Log OddsLogistic Regression: Decision BoundaryLikelihood under the Logistic ModelTraining the Logistic ModelGradient Descent 逻辑回归分类 考虑二分类问题,其中每个样本由一…

【webpack】HMR热更新原理

本文:参考文章 一、HMR是什么,为什么出现 1、出现的原因 之前,应用的加载、更新都是一个页面级别的操作,即使单个代码文件更新,整个页面都要刷新,才能拿到最新的代码同步到浏览器,导致会丢失…

【附安装包】Proteus 8.13安装教程

软件下载 软件:Proteus版本:8.13语言:简体中文大小:447.33M安装环境:Win11/Win10/Win8/Win7硬件要求:CPU2.5GHz 内存4G(或更高)下载通道①百度网盘丨下载链接:https://pan.baidu.co…

1992-2022年全国31省市产业升级、产业结构高级化水平面板数据(含原始数据和计算过程)

1992-2022年全国31省市产业升级、产业结构高级化水平面板数据(含原始数据和计算过程) 1、时间:1992-2022年 2、指标:地区生产总值、第一产业增加值、第二产业增加值、第三产业增加值、第一产业占GDP比重、第二产业占GDP比重、第…

jQuery实现表格最后增加一行和删除最后一行

HTML代码 <div><table><thead><tr><th>成绩表</th></tr></thead><tbody><tr><td>科目</td><td>成绩</td></tr><tr><td>语文</td><td>80</td></…

unittest框架的使用

先简单介绍一下unittest的核心组成部分&#xff1a; 测试夹具&#xff1a;Test Fixture 一般用于执行测试用例的准备或者清理工作&#xff0c;比如测试开始前的数据准备或者测试结束的数据清理等。通过setUp()、tearDown()、setUpClass()、tearDownClass()这四个钩子函数实现了…

YOLOv5目标检测模型训练超参数总结记录

整个YOLO系列的模型除了v1和v2比较古老没有实际项目应用过以外&#xff0c;从v3-v8或多或少都有实践&#xff0c;其中以v5使用频度最高&#xff0c;最早期刚接触YOLO的时候也是一通原理详解学习各种结构可视化&#xff0c;后面实际项目开发越来越多&#xff0c;对于前面的记忆就…

一、Mycat2介绍与下载安装

第一章 入门概述 1.1 是什么 Mycat 是数据库中间件。 1、数据库中间件 中间件&#xff1a;是一类连接软件组件和应用的计算机软件&#xff0c;以便于软件各部件之间的沟 通。 例子&#xff1a;Tomcat&#xff0c;web中间件。 数据库中间件&#xff1a;连接java应用程序和数据库…

解压后的文件丢失怎么恢复?解压文件丢失4种恢复方法

您是否出现过解压文件丢失的情况呢&#xff1f;解压文件通俗易懂地讲就是把压缩好了的文件解开。而有些小伙伴在解压文件以后发现丢失了&#xff0c;这些丢失的文件或许是您重要的img解压文件/rar文件解压/zip解压文件&#xff0c;为了正确解决解压文件丢失问题&#xff0c;下面…

在Visual Studio 2017上配置并使用OpenGL

1 在Visual Studio 2017上配置并使用OpenGL 在GLUT - The OpenGL Utility Toolkit&#xff1a;GLUT - The OpenGL Utility Toolkit中点击“GLUT for Microsoft Windows 95 & NT users”&#xff0c;选择“If you want just the GLUT header file, the .LIB, and .DLL file…

Win7系统电脑开机总出现硬盘自检的简单解决方法

你是不是经常会遇到电脑开机进行硬盘自检&#xff0c;而且每次开机都检查很久不能跳过&#xff1b;怎么才能跳过这一步骤呢&#xff1f;下面教大家如何让Win7系统电脑在开机的时候跳过硬盘自检这一步骤&#xff0c;加快开机时间。 解决步骤&#xff1a; 1、按下“Win R”快捷键…

冠达管理:美联储或已达加息终点,但反弹面临诸多不确定性

本周以来&#xff0c;多项数据显现美国经济正在降温&#xff0c;联邦基金利率期货显现&#xff0c;美联储本轮加息周期或已结束。 于美股而言&#xff0c;正处于高位的货币基金是未来继续上涨的潜在动力。不过&#xff0c;与此前反弹行情的推进力比较&#xff0c;当时的不确定…

SAP:IDCNGRIR_GNB报表展示物料描述与采购订单不一致

1、问题描述&#xff1a; 目前在项目中发现执行SAP的IDCNGRIR_GNB报表的时候&#xff0c;出现了物料编码和订单的物料编码不一致的情况&#xff1a; 2、问题展示&#xff1a; 采购订单上物料及编码显示 IDCNGRIR_GNB报表执行结果显示 3、问题原因&#xff1a; 调试程序发现…