Redis --- 第六讲 --- 关于持久化

前言

持久化:MySQL的事务,有四大比较核心的特性

1、原子性

2、一致性

3、持久性 =》 把数据存储到硬盘上 =》持久,把数据存储在内存上=》持久化。重启进程/重启主机之后,数据是否存在。

4、隔离性

Redis是一个内存数据库,把数据存储在内存中的!

内存中的数据是不持久的。要想能够做到持久,就需要让redis把数据存储到硬盘上。为了保证速度快,数据肯定还是得在内存中,但是为了持久,数据还得想办法存储在硬盘上。Redis决定,内存中也存数据,硬盘上也存数据。这样的两份数据,理论上是完全相同的。实际上可能存在一个小的概率有差异。取决于咱们具体怎么进行持久化。当要插入一个新的数据的时候,就需要把这个数据,同时写入到内存和硬盘,当查询某个数据的时候,直接从内存中读取。硬盘的数据只是在redis重启的时候,用来恢复内存中的数据。代价就是消耗了更多的空间,同一份数据,存储了两遍。说是两边写,但是实际上具体怎么写硬盘还有不同的策略,可以保证整体的效率足够高。

redis实现持久化的时候,具体是按照什么样的策略来实现的呢?

1、RDB =》Redis DataBase,按照定期的方式进行数据持久化。

2、AOF =》 Append Only File,按照实时的方式进行数据持久化。

一、RDB持久化

1、RDB持久化的触发时机

RDB定期的把我们Redis中的所有数据,都给写入硬盘中,生成一个快照。Redis给内存中当前存储的这些数据,拍个照片,生成一个文件,存储在硬盘中,后续Redis一旦重启了,就可以根据刚才的快照把内存中的数据给恢复回来。

定期:具体来说,又有两种方式。

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

save 执行save的时候,redis就会全力以赴的进行快照生成的操作,此时就会阻塞redis的其他客户端的命令。导致类似于keys* 的后果。一般不建议使用save。

bgsave bg=》background后面,不会影响redis服务器处理其他客户端的请求和命令。redis咋做到的?是不是偷摸搞了个多线程?并非如此!并发编程的场景,此处redis使用的是多进程的方式,来完成并发编程,来完成bgsave的实现。

bgsave的执行流程:

父进程就是redis服务器。

第一步:判定当前是否已经存在其他正在工作的子进程。比如现在已经有一个子进程正在进行执行bgsave,此时就直接把当前的bgsave返回。

第二步:如果没有其他的工作子进程,就通过fork这样的系统调用,创建出一个子进程来。 子进程会继承父进程所有的信息。因此,复制出来的这个子进程的内存中的数据就是和父进程是一样的。接下来安排子进程去执行持久化操作,也就相当于把父进程本体这里的内存数据给持久化了。父进程打开了一个文件,fork之后,子进程也是可以同样使用这个文件的。也就导致了子进程持久化写入的那个文件就是和父进程打开的那个文件相同。

如果当前,redis服务器中存储的数据特别多,内存消耗特别大。此时,进行上述的复制操作。是否有很大的开销?

此处的性能开销,其实挺小的。fork在进行内存拷贝的时候,不是简单无脑直接把所有数据都拷贝一遍,而是写时拷贝的机制来完成的!

第三步:子进程负责写文件,生成快照的过程,父进程继续接收客户端的请求,继续正常提供服务。

第四步:子进程完成整体的持久化过程之后,就会使用信号通知父进程,父进程就会更新一些统计信息。子进程就可以结束销毁了。

RDB的rdb文件

redis生成的rdb文件,是存放在redis的工作目录中的,也是在redis配置文件中进行设置的。

可以打开这个目录,可以看到dump.rdb文件,这是rdb机制生成的镜像文件,redis服务器默认就是开启了rdb的。二进制的文件,把内存中的数据,以压缩的形式,保存到这个二进制文件中。压缩:需要消耗一定的cpu资源,但是能节省存储空间。

redis提供了rdb文件的检查工具,来验证rdb文件的格式。

当执行生成rdb镜像操作的时候,此时就会把要生成的快照数据,先保存到一个临时文件中,当这个快照生成完毕之后,再删除之前的rdb文件,把新生成的临时的rdb文件名字改成刚才的dump.rdb自始至终rdb文件只有一个。

2)自动触发。在Redis配置文件中,设置一下,让Redis每隔多长时间/每产生多少次修改就触发。

格式:

自动触发的设置:

虽然此处的这些数值,都可以自由修改设置。但是,此处修改上述数据的时候,要有一个基本的原则。生成一次rdb快照,这个成本是一个比较高的成本,不能让这个操作执行的太频繁。正因为rdb生成的不能太频繁,这就导致,快照里的数据和当前实时的数据情况,可能存在偏差。AOF就是解决这个问题的优化方案。

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

redis生成快照操作,不仅仅是手动执行命令才触发,也可以自动触发。通过刚才配置文件中,save执行M时间内,修改N次。通过shutdown命令关闭redis服务器也会触发。redis进行主从复制的时候,主节点也会自动生成rdb快照,然后rdb快照文件内容传输给从节点。

实际开发中,更害怕的是出现异常情况。

设置key5,kill命令杀掉redis服务器,key5丢失。

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

bgsave操作流程是创建子进程,子进程完成持久化操作,持久化会把数据写入到新的文件中,然后使用新的文件替换旧的文件。可以使用linux命令的stat命令来查看inode编号

文件不再是同一个文件了,只不过内容是一样的。inode编号,就相当于文件的身份标识。Linux文件系统:文件系统典型的组织方式ext4主要是把整个文件系统分成了三个大的部分。

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

使用新的文件,替换旧的文件。

如果使用save命令,此时是不会触发子进程&文件替换这样的设定的。如果是save就直接在当前进程中,往刚才的同一个文件中写入数据了。

通过配置自动生成rdb快照
redis来说,配置文件修改之后,一定要重新启动服务器,才能生效。

如果把rdb文件搞坏了会怎么样?

手动的把rdb文件内容改坏,然后一定是通过kill继承的方式,重新启动redis服务器。但是看起来好像redis服务器没有收到啥影响,还是能正常启动,还是能正确获取到key,如果中间位置坏了可就不一定了。当我们把中间位置改坏了之后,发现redis服务器启动不了了。我们可以查看redis日志,去发现redis发生了什么?

在rdb恢复数据的时候出现问题了。rdb文件时二进制的。直接就把坏了的rdb文件交给redis服务器去使用,得到的结果时不可预期的。可能redis服务器能启动,但是得到的数据可能正确也可能有问题。也可能redis服务器直接启动失败。

redis也提供了rdb文件的检查工具,可以先通过检查工具,检查一下rdb文件格式是否符合要求。

运行的时候,加入rdb文件作为命令行参数,此时就是以检查工具的方式来运行,不会真的启动redis服务器。

总结:

RDB使用二进制的方式来组织数据,AOF时使用文本的方式来组织数据的。则需要进行一系列的字符串切分操作。

老版本的redis的rdb文件,放到新版本的redis中不一定能识别,一般来说,实际工作中,redis版本都是统一的。如果确实需要升级,确实遇到了不兼容的问题。就可以通过写一个程序的方式,直接遍历旧的redis中的所有key,把数据取出来,插入到新的redis服务器中即可。RDB最大的问题,不能实时的持久化保存数据,在两次生成快照之间,实时的数据可能会随着重启而丢失,我们可以使用实时持久化(AOF)来解决这一问题。

二、AOF持久化

AOF的基本使用:

AOF :append only file类似于mysql的binlog,就会把用户的每个操作,都记录到文件中。当redis重新启动的时候,就会读取这个aof文件中的内容,用来恢复数据。当开启AOF的时候,RDB就不生效了。启动的时候就不再读取rdb文件内容了。

aof默认是关闭状态,我们需要通过配置文件打开它。

所在的位置,和RDB文件是相同的。所在的目录可以手动配置。

AOF是一个文本文件,每次进行操作的时候,都会被记录到文本文件中,通过一些特殊符号作为分隔符,来对命令的细节做出区分。

AOF是否会影响到redis的性能

redis虽然是一个单线程的服务器,但是速度快,为啥这样快,重要原因,只是操作内存。引入AOF后,又要写内存,又要写硬盘,还能和之前一样快了吗?

实际上,没有影响到redis处理请求的速度。

1、AOF机制并非是直接让工作线程把数据写入硬盘,而是先写入一个内存中的缓存区,积累一波之后,再统一写入硬盘。

大大降低了写硬盘的次数。

2、硬盘上读写数据,顺序读写的速度是比较快的,随机访问则速度是比较慢的。AOF是每次把新的操作写入到原有文件末尾,属于顺序写入。

AOF缓存区刷新策略

如果把数据写入到缓冲区里,本质还是在内存中,万一这个时候,突然进程挂了,或者主机掉电了,缓存区中没来得及写入硬盘得数据是会丢的。

redis给出了一些选项,让程序员,根据实际情况来决定怎么取舍,缓冲区的刷新策略。刷新频率越高,性能影响就越大,同时数据的可靠性就越高。刷新频率越低,性能影响越小,数据的可靠性就越低。

appendsync

always 频率最高的,数据可靠性最高,性能最低。

everysec 频率低一些,数据可靠性降低,性能会提高。

no 频率最低,数据可靠性最低,性能是最高的。

AOF的重写机制

AOF文件持续增长,体积越来越大。会影响到,redis下次启动的时间,redis启动的时候,要读取aof文件的内容。注意!上述AOF中的文件,有一些内容是冗余的。

AOF文件的内容,记录了中间的过程,实际上redis在重新启动的时候,只是关注最终结果。因此redis就存在一个机制,能够针对aof文件进行整理操作,这个整理就是能够提出其中的冗余操作,并且合并一些操作,达到给AOF文件瘦身这样的效果。

AOF重写机制的触发机制

手动触发:调用bgrewriteaof命令。

自动触发:

AOF重写的流程

父进程仍然负责接收请求,子进程负责针对aof文件进行重写。

注意!重写的时候,不关心aof文件中原来都有啥,只是关心内存中最终的数据状态,子进程只需要把内存中当前的数据,获取出来。以AOF的格式,写入到一个新的AOF文件中,内存中的数据状态,就已经相当于是把AOF文件结果整理后的模样了。

此处子进程写数据的过程,非常类似于RDB生成一个镜像快照,只不过RDB这里按照二进制的方式来生成的。AOF重写,则是按照AOF这里要求的文本格式来生成的。都是为了把当前内存中的所有数据状态记录到文件中!子进程写新AOF文件的同时,父进程仍然在不停的接收客户端的新的请求,父进程还是会先把这些请求产生的AOF数据先写入到缓冲区,再刷新到原有的AOF文件里。

在创建子进程的一瞬间,子进程就继承了当前父进程的内存状态,因此,子进程里的内存数据是父进程fork之前的状态,fork之后,新来的请求,对内存造成的修改,是子进程不知道的。此时,父进程这里又准备了一个aof_rewrite_buf 缓冲区,专门放fork之后收到的数据。

子进程这边,把aof数据写完之后,会通过信号通知一下父进程,父进程再把aof_rewrite_buf缓冲区中的内容也写入到新AOF文件里, 就可以用新的AOF文件代替旧的AOF文件了。

如果,在执行bgrewriteaof的时候当前已经正在进行aof重写了,此时,不会再次执行aof重写,直接返回了。如果在执行bgwriteaof的时候,发现当前redis在生成rdb文件的快照,此时aof重写操作就会等待,等待rdb快照生成完毕之后,再进行执行aof重写。

rdb对于fork之后的新数据,就直接置之不理了,aof则对于fork之后的新数据,采取了aof_rewrite_buf缓冲区的方式来处理。rdb本身的设计理念,就是用来定期备份的。只要是定期备份,就难以和最新的数据保持一致。aof的理念则是实时备份,实时备份不一定就比定期备份更好,还是要看实际场景的。现在的系统中,系统的资源一般都是比较充裕的。aof的开销也不算事情,一般来说aof的适用场景更多一些。

当前父进程fork完毕之后,就已经让子进程写新的aof文件了,并且随着时间的推移,子进程很快就写完了新的文件,要让新的aof文件代替旧的aof文件,父进程此时还在继续写这个即将消亡的旧的aof文件是否还有意义?这是有意义的。不能不写,考虑到极端情况,假设在重写过程中,服务器掉电了。服务器挂了,此时子进程内部的数据就会丢失,新的aof文件内容还不完整,所以如果父进程不坚持写旧的aof文件,重启就没法保证数据的完整性了。

混合持久化

AOF本来是按照文本的方式来写入文件的,但是文本的方式写文件,后续加载的成本是比较高的。redis就引入了混合持久化的方式,结合了rdb和aof的特点。按照aof的方式,每一次请求/操作,都记录到文件中,在触发aof重写之后,就会把当前内存状态按照rdb的二进制格式写入到新的aof文件中。后续再进行的操作,仍然是按照文本的方式追加到AOF文件中。

开启混合持久化。

当redis上同时存在aof文件和rdb快照的时候,此时以aof为主,rdb就被忽略了。

这是因为AOF中包含的数据比RDB更全。

信号通知父进程:信号这个东西,可以认为是Linux的神经系统。进程之间的相互作用(也可以视为是进程间通信的一种手段)。但是java生态中并不鼓励使用多进程模型编程,网络通信的场景除外。

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

如何在忘记密码的情况下解锁 iPhone? 6 种方法分享

您是否因为没有密码而无法解锁您的 iPhone? 别担心,这种情况比你想象的更常见!忘记密码是 iPhone 用户面临的最常见问题之一,而且可能非常令人沮丧 - 但不要绝望。 在这篇文章中,我们将与您分享绕过 iPhone 屏幕密码…

No provider available from registry RegistryDirectory

【中】No provider available from registry RegistryDirectory Dubbo 3.2.9Nacos 2.1.0 最近在做配置文件升级,服务比较多,之前的Dubbo配置各个服务写的比较乱,有的用Nacos上的 data-id,有的又是在自己的服务引入配置 遂准备统一…

记录一次从nacos配置信息泄露到redis写计划任务接管主机

经典c段打点开局。使用dddd做快速的打点发现某系统存在nacos权限绕过 有点怀疑是蜜罐,毕竟nacos这实在是有点经典 nacos利用 老规矩见面先上nacos利用工具打一波看看什么情况 弱口令nacos以及未授权访问,看这记录估计被光顾挺多次了啊 手动利用Nacos-…

软件测试与软件缺陷的基础知识

✨✨ 欢迎大家来访Srlua的博文(づ ̄3 ̄)づ╭❤~✨✨ 🌟🌟 欢迎各位亲爱的读者,感谢你们抽出宝贵的时间来阅读我的文章。 我是Srlua小谢,在这里我会分享我的知识和经验。&am…

秋招面试题记录_半结构化面试

c八股(可能问的多一点) 1.简单说说C11语法特性 答: 1.auto以及decltype自动类型推导,避免手动声明复杂类型,减少冗长代码提升了可读性和安全性。 2.智能指针 自动释放内存 (具体说说) 有shared和unique 差异主要体现在所有权、内存开销、…

Tesseract OCR 安装

Tesseract OCR 的安装步骤因操作系统的不同而有所区别。以下是针对 Windows、macOS 和 Linux 系统的详细安装指导。 1. Windows 步骤: 下载 Tesseract 安装程序 访问 Tesseract GitHub Release 页面。下载最新版本的安装程序(例如 .exe 文件&#xff0…

【小趴菜前端实习日记5】

实习日记5 一、vue3中如何使用router(获取this)二、ts中用object定义类型太宽泛导致Ts无法推断出正确类型三、动态设置日记封面失败vite动态引入静态资源1.方法一vue3父子组件生命周期执行顺序 2.方法二3.方法三 四、打包问题总结1.The import.meta meta-property i…

整理—Redis

目录 Redis底层的数据结构 ZSet用过吗 Zset 底层是怎么实现的 跳表是怎么实现的? Redis为什么使用跳表而不是用B树? 压缩列表是怎么实现的? Redis 中的 listpack 哈希表是怎么扩容的? String 是使用什么存储的 Redis为什么快&#xf…

最好的ppt模板网站是哪个?做PPT不可错过的18个网站!

现在有很多PPT模板网站,但真正免费且高质量的不多,今天我就分享主流的国内外PPT模板下载网站,并且会详细分析这些网站的优缺点,这些网站都是基于个人实际使用经验的,免费站点会特别标注,让你可以放心下载&a…

C++:模板(2)

目录 非类型模板参数 模板的特化 概念 函数模板特化 类模板特化 全特化 偏特化 模板的分离编译 分离编译的概念 模板的分离编译 ​编辑 模板总结 非类型模板参数 模板参数分为类型形参与非类型形参。 类型形参:在模板参数列表中,跟在class…

STM32L1x 片上温度传感器采用ADC及工厂校准数据提升测量温度精度

背景 由于项目临时需要温度数据,又不想改动硬件了,反正对温度精度要求不算太高,索性就用MCU片上温度传感器的温度,来替代了。这里自己根据网上帖子做了一些测试用例尝试测温,但是,效果都不理想。发现ST官方…

得物App3D博物馆亮相“两博会”,正品保障助力消费体验升级

近日,2024中国体育文化博览会、中国体育旅游博览会(以下简称“两博会”)在苏州国际展览中心盛大开幕。本次展会汇聚了众多国内外体育文化、体育旅游领域的顶尖企业和品牌,共同展示体育产业的发展成果和最新趋势。在C展馆C21展位&a…

Adams函数构建器(Function Builder)教程来了

学会使用函数构建器是在进行Adams仿真分析的必备技能,通过函数构建器可以查询和使用Adams的各种设计时函数和运行时函数,并能够构建用户自己的函数,大多数情况下的力或者驱动都不是简单的数字,而是需要函数来驱动的,那…

GEE数据集:2001年-2019年全球土地覆被估算(GLanCE)

目录 简介 数据集说明 空间信息 代码1 代码2 代码链接 APP链接 结果 引用 许可 网址推荐 知识星球 机器学习 简介 全球土地覆被估算(GLanCE) 全球土地覆被估算(GLanCE)数据集利用 30 米空间分辨率的大地遥感卫星图…

【拯救头痛大作战!有效应对焦虑引发的“脑内风暴”】

在这个快节奏、高压力的时代,焦虑似乎成了许多人难以摆脱的“隐形伴侣”。它不仅悄无声息地侵蚀着我们的心理健康,还可能引发一系列生理反应,其中最常见也最让人苦恼的便是——焦虑导致的头疼。今天,就让我们一起探索如何有效应对…

Linux介绍及常用命令

Linux 系统简介 1969 年,AT&T 公司的⻉尔实验室P MIT 合作开发的 Unix,在于创建⼀个⽤于⼤型、并⾏、多⽤户的操作系统Unix 的推⼴:从学校⾛进企业Unix 的版本要两个: AT&T System V ——就是俗称的 系统 5Berkley Soft…

【数据结构】-数组

数组 特点: 数组的地址连续,可以通过下标获取数据。 1. 数组扩容 步骤: $1. 创建一个比原来数组更长的新数组 $2. 让原来数组当中的数据依次复制到新数组当中 $3. 让arr指向新数组,原数组空间释放 2. 数组插入 2.1 最后位置…

kotlin 入门总结

目录 1、构造函数 2、数据类 data class, 3、object 单例类,相当于java线程安全的懒加载 4、companion object 伴生对象,类似于包装静态值的一个区域块 5、解构 6、空安全 7、条件语句 8、集合 9 属性和支持属性 属性 支持属性 10 …

HarmonyOS Next模拟器异常问题及解决方法

1、问题1:Failed to get the device apiVersion. 解决方法:关闭模拟器清除用户数据重启

【java】数组(超详细总结)

目录 一.一维数组的定义 1.创建数组 2.初始化数组 二.数组的使用 1.访问数组 2.遍历数组 3.修改数据内容 三.有关数组方法的使用 1.toString 2. copyOf 四.查找数组中的元素 1.顺序查找 2.二分查找binarySearch 五.数组排序 1.冒泡排序 2.排序方法sort 六.数组逆置…