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生态中并不鼓励使用多进程模型编程,网络通信的场景除外。

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

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

相关文章

消息队列(仿RabbitMQ)—— 生产消费模型

本篇将实现一个3000多行的一个小项目,基于AMQP(高级消息队列协议)的消息队列,主要仿照 RabbitMQ 实现该代码,其本质也是生产消费模型的一个升级版本。实现的功能为:消息发布端将消息发送到服务器端&#xf…

如何开启华为交换机 http

系列文章目录 提示:这里可以添加系列文章的所有文章的目录,目录需要自己手动添加 例如:第一章 Python 机器学习入门之pandas的使用 提示:写完文章后,目录可以自动生成,如何生成可参考右边的帮助文档 文章目…

腾讯 C++ 客户端一面,居然遇见了一道简单题。它怎么用go、C++解决

腾讯是目前全国最强的互联网公司之一,它有很好的福利尤其是能给应届生不错的工资待遇。 也正因如此,想进入腾讯工作的难度和竞争的激烈程度非常之大。 虽然感觉腾讯像是更看重个人综合能力的一家公司,算法题的好坏占面评比相对小些 但是竞争…

二、Linux 系统命令

一、系统命令 # 清屏 (Ctrl L) $ clear# 退出登录 $ exit # 历史命令 $ history $ history | grep java -jar 1. 系统信息 # 查看版本,当前操作系统发行版信息 $ cat /etc/redhat-release CentOS Linux release 7.2.1511 (Core) # 查看操作系统位数 $ getco…

【2022工业3D异常检测文献】Patch+FPFH: 结合3D手工点云描述符和颜色特征的异常检测方法

AN EMPIRICAL INVESTIGATION OF 3D ANOMALY DETECTION AND SEGMENTATION 1、Background PatchCore 方法: PatchCore是一种基于2D图像的异常检测方法,它使用预训练的深度学习模型(如在ImageNet上预训练的模型)来提取图像的局部特…

Memory Bus in SOC

在 SoC架构设计中,Memory Bus 是一个关键的组成部分,它负责连接 SoC 中的各个模块(如 CPU、GPU、DMA、外设等)与外部存储器(如 DDR、NAND、Flash 等),起到连接处理器和存储器之间的桥梁作用&…

Qt优秀开源项目之二十四:EXCEL读写利器QXlsx

QXlsx是基于Qt5/Qt6的Excel文件(*.xlsx)的读写库。 github地址:https://github.com/QtExcel/QXlsx QXlsx既可以编译成库,也可以直接引用源码QXlsx-master\QXlsx\QXlsx.pri QXls提供了非常丰富的Examples,比如&#xff…

LED电子看板减少人工记录的错误

在当今快节奏的生产和管理环境中,准确性和效率是企业追求的关键目标。而传统的人工记录方式,常常因人为因素而出现各种错误,影响着企业的决策和运营。然而,随着科技的不断进步,LED 电子看板的出现为解决这一难题提供了…

无法获得下列许可 SOLIDWORKS Standard。 无法从使用许可服务器内读取数据,(-16,10009,10054)

无法获得下列许可 SOLIDWORKS Standard。 无法从使用许可服务器内读取数据,(-16,10009,10054) 错误如图 打开xxclean 扩展功能 服务无法启动

10.23Python_matplotlib_乱码问题

中英文问题解决方案 在使用 Matplotlib 绘图时,经常会出现中文字体显示问题。以下是一些解决方案: Windows 系统解决方案 在代码开始处添加以下代码,以支持中文显示: import matplotlib.pyplot as plt plt.rcParams[font.sans…

联想与Meta合作基于Llama大模型推出面向PC的个人AI智能体——AI Now | LeetTalk Daily...

“LeetTalk Daily”,每日科技前沿,由LeetTools AI精心筛选,为您带来最新鲜、最具洞察力的科技新闻。 联想集团昨日在美国西雅图召开年度Tech World大会。联想CEO杨元庆在主题演讲中,与Meta创始人兼CEO马克扎克伯格一道宣布&#x…

《15分钟轻松学Go》教程目录

在AI快速发展的时代,学习Go语言依然很有用。Go语言擅长处理高并发任务,也就是说可以同时处理很多请求,这对于需要快速响应的AI服务非常重要。另外,Go适合用来处理和传输大量数据,非常适合机器学习模型的数据预处理。 …

C++笔记---哈希表

1. 哈希的概念 哈希(hash)又称散列,是一种组织数据的方式。从译名来看,有散乱排列的意思。 本质就是通过哈希函数把关键字Key跟存储位置建立一个映射关系,查找时通过这个哈希函数计算出Key存储的位置,进行快速查找。 STL中的un…

【Python数据库操作】使用SQLite和MySQL进行数据存储和查询!

【Python数据库操作】使用SQLite和MySQL进行数据存储和查询! 在现代应用程序中,数据存储与管理是至关重要的。Python为开发者提供了多种与数据库进行交互的方式,其中SQLite和MySQL是最常用的两种数据库。本文将深入探讨如何使用Python进行SQ…

No.20 笔记 | WEB安全 - 任意文件操作详解 part 2

一、文件后缀名验证 (一)验证方式分类 基于白名单验证:只允许上传白名单中指定后缀名的文件。基于黑名单验证:只允许上传黑名单中未包含后缀名的文件。 (二)实验准备 修改 Apache 的 httpd - conf 文件…

uni-app写的微信小程序如何体积太大如何处理

方法一:对主包进行分包处理,将使用url: /pages/components/equipment/equipment跳转页面的全部拆分为分包,如url: /pagesS/components/equipment/equipment 在pages.json中添加 "subPackages": [{ "root"…

2024年五一杯数学建模C题煤矿深部开采冲击地压危险预测求解全过程论文及程序

2024年五一杯数学建模 C题 煤矿深部开采冲击地压危险预测 原题再现: “煤炭是中国的主要能源和重要的工业原料。然而,随着开采深度的增加,地应力增大,井下煤岩动力灾害风险越来越大,严重影响着煤矿的安全高效开采。在…

transient关键字详解

今天没打算写blog,在看一篇关于多线程环境下SimpleDateFormat线程不安全的问题,一般我们都知道多线程下这个是不安全,但是为什么不安全不太清楚,我在看的这篇文章讲的比较透彻,我根据文章中讲结合SimpleDateFormat源码…

[Unity Demo]从零开始制作空洞骑士Hollow Knight第十五集:制作更多地图,更多敌人,更多可交互对象

提示:文章写完后,目录可以自动生成,如何生成可参考右边的帮助文档 文章目录 前言一、第一个代表性场景 1.制作更多敌人2.制作更多可交互对象二、第二个代表性场景 1.制作更多敌人2.制作更多可交互对象三、第三个代表性场景 1.制作更多敌人2.制…

苹果手机照片误删还能恢复吗?3款数据恢复工具推荐

照片是人们记录生活点滴与美好回忆的重要方式之一。而苹果手机则具备了较强的拍照功能,深受市场欢迎,但其也存在误删照片并难以恢复的难题。现在市面上也又很多照片恢复软件,其功能参差不齐。今天,小编为您找到了3款高效且可靠的苹…