Redis——持久化

文章目录

  • Redis持久化
    • Redis的两种持久化的策略
      • 定期备份:RDB
        • 触发机制
        • rdb的触发时机:
        • 手动执行save&bgsave保存测试
        • 不手动执行bgsave测试
        • bgsave操作流程测试
        • 通过配置,自动生成rdb快照
        • RDB的优缺点
      • 实时备份:AOF
        • AOF是否会影响到redis的性能
        • AOF的重写机制
          • 重写触发方式
          • AOF重写的流程
      • 总结

Redis持久化

在这之前要提及到Mysql的事务的四个比较核心的特性

原子性 一致性 持久性 隔离性

这里mysql的持久性就是把数据存储在硬盘上,而redis数据是存在内存里的,要想做到持久,就需要让redis把数据存储到硬盘上

Redis相比于Mysql这样的关系型数据库,最明显的特点/优势就是 快,所以为了保证速度快,数据肯定还是得在内存中,但是为了持久,数据还得办法存储在硬盘上

Redis决定 内存中也存数据,硬盘上也存数据,这样的两份数据,理论上是完全相同的

  • 当要插入一个新的数据的时候,就需要把这个数据同时写入到内存和硬盘(说是两边都写,但是实际上具体怎么写硬盘还有不同的策略,可以保证整体的效率还是足够的高)
  • 当查询某个数据的时候,直接从内存读取
  • 硬盘的数据只是在redsi重启的时候,用来恢复内存中的数据
  • 代价就是消耗了更多的空间,同一份数据,存储了两遍(但是毕竟硬盘比较便宜,这样的开销并不会带来太多的成本)

Redis的两种持久化的策略

  1. RDB => Redis DataBase 定期备份:每隔一段时间,进行一次备份
  2. AOF => Append Only File 实时备份:只要有数据变动,立即备份

定期备份:RDB

RDB 持久化是把当前进程数据生成快照保存到硬盘的过程,触发 RDB 持久化过程分为手动触发自动触发

触发机制
  • 手动触发:通过redis客户端执行特定的命令,来执行快照生成 (手动触发分别对应 save 和 bgsave 命令)

• save 命令:阻塞当前 Redis 服务器,直到 RDB 过程完成为止,对于内存比较大的实例造成长时间阻塞,基本不采用
• bgsave 命令:Redis 进程执行 fork 操作创建子进程,RDB 持久化过程由子进程负责,完成后自动结束。阻塞只发生在 fork 阶段,⼀般时间很短。

Redis 内部的所有涉及 RDB 的操作都采用类似 bgsave 的方式。

在这里插入图片描述

  1. 执行 bgsave 命令,Redis 父进程判断当前进是否存在其他正在执行的子进程,如 RDB/AOF 子进
    程,如果存在 bgsave 命令直接返回。
  2. 父进程执行 fork 创建子进程,fork 过程中父进程会阻塞,通过 info stats 命令查看latest_fork_usec 选项,可以获取最近⼀次 fork 操作的耗时,单位为微秒。
  3. 父进程 fork 完成后,bgsave 命令返回 “Background saving started” 信息并不再阻塞父进程,可以继续响应其他命令。
  4. 子进程创建 RDB 文件,根据父进程内存生成临时快照文件,完成后对原有文件进行原子替换。执行 lastsave 命令可以获取最后⼀次生成 RDB 的时间,对应 info 统计的 rdb_last_save_time 选项。
  5. 进程发送信号给父进程表⽰完成,父进程更新统计信息。
  • 自动触发:在Redis配置文件中,设置一下,让Redis每隔多长时间/每产生多少次修改 就触发

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

在这里插入图片描述

这里的dump.rdb文件,就是rdb机制生成的镜像文件,redis服务器默认就是开启了rdb的,这个镜像文件,是一个二进制的文件,把内存中的数据,以压缩的形式,保存到这个二进制文件中

后续redis服务器重新启动,就会尝试加载这个rdb文件,如果发现格式有错误,就可能会加载数据失败

rdb文件,虽然我们没有主动去动他,但是也有可能会出现一些意外问题,一旦通过一些操作(比如网络传输)引起这个文件被破坏,此时redis服务器就无法启动

  • redis提供了rdb文件的检查工具 redis-check-rdb

查看一下RDB文件里面是什么内容

在这里插入图片描述

里面都是二进制内容,当我们对redis文件中的数据进行增删查改时,这里的RDB文件并不会立即更新

rdb的触发时机:
  1. 手动(save,bgsave)
  2. 自动(配置文件中,进行设置)

在这里插入图片描述

在这里插入图片描述

save //seconds之内至少存在changes次key的修改

虽然此处的这些数值,都可以自由修改配置,但是此处修改上述数据的时候,要有一个基本规则

生成一次rdb快照,这个成本是一个比较高的成本,不能让这个操作执行的太频繁

正因为rdb不能生成的太频繁,这就导致,快照里的数据,和当前实时的数据情况可能会存在偏差

save 60 10000 (两次生成rdb之间的间隔,至少得是60s)

假设当前

12:00:00生成了rdb(硬盘上的快照数据和内存中一致)

12:00:01开始,redis收到了大量的key的变化请求

12:01:00生成下一个快照文件

在上述过程之间,redis服务器挂了,此时就会导致,12:00:00之后的这些数据,就丢了(数新的据只是在内存里,还没存到rdb)

手动执行save&bgsave保存测试

由于这里执行的数据比较少,所以瞬间就完成了,立即查看应该是有结果的,如果数据比较多,执行bgsave就需要消耗一定的时间,立即查看不一定就是生成完毕了

在这里插入图片描述

保存后查看rdb文件可以看到已经发生了修改

在这里插入图片描述

持久化验证,可以看到,通过上述操作,redis服务器在重新启动的时候,加载了rdb文件的内容,恢复了内存中之前的状态

在这里插入图片描述

redis生成快照操作,不仅仅是手动执行命令才触发,也可以自动触发~

  1. 通过配置文件中save执行M时间内,修改N次…
  2. 通过shotdown命令(redis里的一个命令)关闭redis服务器,也会触发
  3. redis进行主从复制的时候,主节点也会自动生成rdb快照,然后把rdb快照文件内容传输给从节点
不手动执行bgsave测试

插入新的key,不手动执行bgsave,重新启动redis服务器

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

bgsave操作流程测试

bgsave操作流程是创建子进程,子进程完成持久化操作,持久化会把数据写入到新的文件中,然后使用新的文件替换旧的文件

而子进程完成持久化的速度太快了(数据少),难以观察到子进程,但是我们可以通过文件的inode来验证bgsave操作流程

在这里插入图片描述

在redis客户端执行bgsave后

在这里插入图片描述

可以看到Inode从18685044变为了18685080

通过配置,自动生成rdb快照

这里执行flashall也会自动生成rdb快照

在这里插入图片描述

将时间设置为60秒 设置两次保存rdb

在这里插入图片描述

在这里插入图片描述

如果rdb文件故意改坏了,会怎样

如果改的是结尾的位置,基本没什么影响,如果改的hi中间的位置,那么redis服务器就会挂掉

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

在这里插入图片描述

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

redis-check-rdb dump.rdb

RDB的优缺点
  • RDB 是⼀个紧凑压缩的二进制文件,代表 Redis 在某个时间点上的数据快照。非常适用于备份,全量复制等场景。比如每 6 小时执行 bgsave 备份,并把 RDB 文件复制到远程机器或者文件系统中 (如 hdfs)用于灾备。

  • Redis 加载 RDB 恢复数据远远快于 AOF 的方式。

  • RDB 方式数据没办法做到实时持久化 / 秒级持久化。因为 bgsave 每次运行都要执行 fork 创建子进程,属于重量级操作,频繁执行成本过高。

  • RDB 文件使用特定二进制格式保存,Redis 版本演进过程中有多个 RDB 版本,兼容性可能有风险。

实时备份:AOF

Append Only File

类似于mysql的binlog,会把用户的每个操作,都记录到文件中,当redis重新启动的时候,就会读取这个aof文件中的内容,用来恢复数据

在这里插入图片描述

将这个appendonly的属性设置为 yes后,重启redis服务器,这里我执行两次set命令后查看 /var/lib/redis目录下的文件,发现多了一个文件appendonly.aof

在这里插入图片描述

由文件内容可以看到,AOF是一个文本文件,每次进行的操作都会被录到文本文件中,通过一些特殊的符号作为分隔符,来对命令的细节进行区分

AOF是否会影响到redis的性能

redis虽然是一个单线程的服务器,但是速度很快,引入AOF后,又要写内存,又要写硬盘,还能和之前一样快了吗?

实际上,是没有影响的

  1. AOF机制并非是直接让工作线程把数据直接写入硬盘,而是先写入一个内存的缓冲区,积累一波后,再统一写入硬盘(假设由100个请求,100个请求一次写入硬盘,比分100次写入一个请求要快得多,写硬盘的时候,写入硬盘的数据的多少,对于性能影响没有很大,但是写入硬盘的次数则影响很大)

在这里插入图片描述

  1. 硬盘上读写数据,顺序读写的速度是比较快的(还是比内存要慢得多)随机访问则速度是比较慢的,而AOF是每次把新的操作写到原有文件的末尾,属于 顺序写入

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

redis给出了一些选项,让程序猿,根据实际情况决定怎么取舍,缓冲区的刷新策略

刷新频越越高,性能影响就越大,同时数据的可靠性就越高

刷新频率越低,性能影响就越小,数据的可靠性就越低~~

可配置值说明取舍情况
always命令写入aof_buf 后调用 fsync 同步,完成后返回频率最高,数据可靠性最高,性能最低
everysec命令写入aof_buf 后只执行 write 操作,不进行 fsync。每秒由同步线程进行 fsync。频率低一些,数据可靠性也会降低,性能会提高
no命令写入 aof_buf 后只执行 write 操作,由 OS 控制 fsync 频率。频率最低,数据可靠性也是最低的,性能是最高的

在这里插入图片描述

通过配置文件可以看到redis默认是everysec策略

AOF的重写机制

AOF文件持续增长,体积越来越大,会影响到redis下次启动的启动时间,redis启动的时候要读取aof文件的内容

redis存在一个机制,能够对aof文件进行整理操作,这个整理就是能够提出其中的冗余操作,并且合并一些操作,达到给aof文件瘦身这样的效果,例如lpush 111 ,lpush 222 合并为 lpush 111 222

重写触发方式
  • 手动触发:调用bgrewriteaof命令
  • 自动触发:根据auto-aof-rewrite-min-size和auto-aof-rewrite-percentage参数确定自动触发时机。
    • auto-aof-rewrite-min-size:表示触发重写时AOF的最小文件大小,默认为64MB
    • auto-aof-rewrite-percentage:代表当前AOF占用大小相比较上次重写时增加的比例
AOF重写的流程

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

注意: 重写的时候,不关心aof文件中原来都有啥,只是关心内存中的最终的数据状态!

子进程只需要把内存中当前的数据,获取出来,以AOF的格式写入到一个新的AOF文件中

此处子进程写数据的额过程,非常类似于RDB生成一个镜像快照,只不过RDB这里是按照二进制的方式来生成的,AOF重写则是按照AOF这里的要求的文本格式来生成的

在这里插入图片描述

在创建子进程的一瞬间,子进程就继承了当前父进程的内存状态,因此子进程里的内存数据是父进程fork之前的状态,fork之后,新来的请求,对内存造成的修改,是子进程不知道的

此时父进程这里又准备额一个aof_rewrite_buf缓冲区,专门放fork之后收到的数据,子进程这边,把aof数据写完之后,会通过信号通知一下父进程,父进程再把aof_rewrite_buf缓冲区中的内容也谢入到新AOF文件里

就可以用新的AOF文件代替旧的AOF文件了

如果,在执行bgrewriteaof的时候,当前redis已经正在进行aof重写了,会咋样呢?? ————此时不会再次执行aof重写,直接就返回了

如果,在执行bgrewriteaof的时候,当前redis已经正在进行生成rdb文件快照,会咋样呢?? ——此时aof重写操作就会等待,等待rdb快照生成完毕之后,再进行执行aof重写

rdb对于fork之后的新数据,就置之不理了,aof则对于fork之后的新数据,采取了aof_rewrite_buf缓冲区的方式来处理

父进程fork完毕之后,就已经让子进程写心得aof文件了,并且随着时间的推移,子进程很快就写完了新的文件 ,要让新的aof文件代替旧的,父进程此时还在继续写这个即将消亡的旧的aof文件是否还有意义??

这里就要考虑到一种极端的情况

假设重写过程中,重写了一半,服务器挂了,子进程内存的数据就会丢失,新的aof文件内容还不完整,所以如果父进程不坚持写旧的aof文件,重启就没法保证数据的完整性

在这里插入图片描述

打开aof文件可以看到所有的操作都被记录了下来

在这里插入图片描述

查看一下执行bgrewriteaof之前的aof文件信息

在这里插入图片描述

执行一下bgrewriteaof再查看aof文件信息

在这里插入图片描述

查看aof文件内容会发现已经变了, 并且会变成二进制

在这里插入图片描述

为什么会变成二进制呢?

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

在这里插入图片描述

在配置文件中,可以选择是否开启混合持久化

当redis上同时存在aof文件和rdb快照的时候,此时以谁为主?以aof为主!!rdb直接被忽略了(因为AOF中包含的数据比RDB更全)

在这里插入图片描述

总结

  1. Redis 提供了两种持久化方案:RDB 和 AOF。

  2. RDB 视为内存的快照,产生的内容更为紧凑,占用空间较小,恢复时速度更快。但产生 RDB 的开
    销较⼤,不适合进行实时持久化,⼀般用于冷备和主从复制。

  3. AOF 视为对修改命令保存,在恢复时需要重放命令。并且有重写机制来定期压缩 AOF 文件。

  4. RDB 和 AOF 都使用 fork 创建⼦进程,利用 Linux ⼦进程拥有⽗进程内存快照的特点进行持久化,
    尽可能不影响主进程继续处理后续命令。

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

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

相关文章

基于opencv答题卡识别判卷

我们是一个深度学习领域的独立工作室。团队成员有:中科大硕士、纽约大学硕士、浙江大学硕士、华东理工博士等,曾在腾讯、百度、德勤等担任算法工程师/产品经理。全网20多万粉丝,拥有2篇国家级人工智能发明专利。 社区特色:深度实…

【Qt】窗口预览(1)—— 菜单栏

窗口预览(1) 1. QMainWindow2. QMenuBar——菜单栏2.1 创建菜单栏/将菜单栏添加到widget中2.2 addMenu——在菜单栏中添加菜单2.3 在菜单中添加选项2.4 添加快捷键2.5 支持嵌套添加菜单2.6 添加信号2.7 添加分割线 1. QMainWindow Qt窗口是通过QMainWin…

基于SSM框架学籍管理系统的设计与实现

我 | 在这里 ⭐ 全栈开发攻城狮、全网10W粉丝、2022博客之星后端领域Top1、专家博主。 🎓擅长 指导毕设 | 论文指导 | 系统开发 | 毕业答辩 | 系统讲解等。已指导60位同学顺利毕业 ✈️个人公众号:乡下小哥编程。回复 Java全套视频教程 或 前端全套视频教…

微信小程序和抖音小程序的分享和广告接入代码

开发完成小程序或者小游戏之后,我们为什么要接入分享和广告视频功能,主要原因有以下几个方面。 微信小程序和抖音小程序接入分享和广告功能主要基于以下几个原因: 用户获取与增长:分享功能可以帮助用户将小程序内容传播给更多人&…

# 在执行 rpm 卸载软件使用 nodeps 参数时,报错 error: package nodeps is not installed 分析

在执行 rpm 卸载软件使用 nodeps 参数时,报错 error: package nodeps is not installed 分析 一、问题描述: 在执行 rpm 卸载软件使用 nodeps 参数时,报错 error: package nodeps is not installed 如下图: 二、报错分析&…

【HarmonyOS NEXT】实现页面水印功能

关键词:鸿蒙、水印、Watermark、页面、触摸问题 注:本期文章同样适用 OpenHarmony 的开发 在app开发过程中时常会出现敏感信息页面,为保护信息安全和及时的数据追踪,通常会采用给页面加水印的形式,那么本期文章会介绍…

ARC学习(4)基本编程模型认识(四)----寄存器以及异常数据读取

笔者来聊一下ARC寄存器的获取 在介绍了ARC编程模型的知识点之后,来看一些具体的编程操作,比如如何获取寄存器,如何编写汇编语言实现特定功能? 1、获取寄存器 可以使用内联汇编来实现寄存器的获取,具体格式如下: _Asm:汇编宏标识符,指示内联汇编代码_Save_all_regs:…

轻量服务器和云服务器ecs哪个好用一些?

轻量服务器和云服务器ecs哪个好用一些?轻量服务器与云服务器ECS在多方面存在显著差异,对于需要高性能计算和大规模数据处理的用户来说,ECS可能是更好的选择;而对于预算有限且需求较为简单的用户来说,轻量服务器可能更为…

Node.js入门——fs、path模块、URL端口号、模块化导入导出、包、npm软件包管理器

Node.js入门 1.介绍 定义:跨平台的JS运行环境,使开发者可以搭建服务器端的JS应用程序作用:使用Node.Js编写服务器端代码Node.js是基于Chrome V8引擎进行封装,Node中没有BOM和DOM 2.fs模块-读写文件 定义:封装了与…

分布式事务管理-Seata从入门到精通

一、基本概念 什么是数据库事务? 1、一个操作数据库数据的执行单元 2、到围从开始到结束的多个操作组成 3、事务内的多个操作要么都成功,要么都失败 什么是分布式事务? 1.分布式场景下,完成某一个业务功能可能需要横跨多个服务&#xff0…

jmeter入门:脚本录制

1.设置代理。 网络连接-》代理-》手动设置代理. ip: 127.0.0.1, port:8888 2. add thread group 3. add HTTP(s) test script recorder, target controller chooses Test plan-> thread Group 4. click start. then open the browser …

AIGC毕设项目分享:基于RAG的数字人对话系统及其应用

本研究的主要目标是设计并实现一个基于检索增强生成(RAG)技术的数字人对话系统,旨在提升数字人系统在多轮对话中的上下文管理、情境感知能力以及动态内容生成效果。系统结合了深度学习中的最新大语言模型技术,通过引入RAG框架来增…

ubuntu下route命令详解

buntu下route命令详解 1、显示路由表 route -n2、临时路由设置,重启网卡失效#添加一条路由(发往192.168.62这个网段的全部要经过网关192.168.1.1)route add -net 192.168.62.0 netmask 255.255.255.0 gw 192.168.1.1#删除一条路由 删除的时候不用写网关route del …

华为海思:大小海思的双轮驱动战略分析

华为海思,作为华为旗下的半导体设计部门,近年来在芯片设计领域取得了显著成就,成为了中国乃至全球芯片设计的重要力量。实际上,华为海思并非单一实体,而是由两个主要分支构成:大海思和小海思。这两个分支虽然同属华为海思,但在定位、产品布局以及市场策略上有所不同,共…

【测试】BUG篇——BUG

bug的概念 定义:⼀个计算机bug指在计算机程序中存在的⼀个错误(error)、缺陷(flaw)、疏忽(mistake)或者故障(fault),这些bug使程序⽆法正确的运⾏。Bug产⽣于程序的源代码或者程序设计阶段的疏忽或者错误。 准确的来说: 当且仅当规格说明&am…

【大数据技术基础 | 实验二】Linux基础:常用基本命令和文件操作

文章目录 一、实验目的二、实验要求三、实验环境四、常用基本命令1、验证cd和pwd命令2、验证ls命令3、验证mkdir命令4、验证cp、mv和rm命令 五、Linux文件操作1、验证touch命令2、验证cat命令3、验证more命令 六、实验心得 一、实验目的 学会linux常用命令(cd,ls,pwd,mkdir,rm…

【Flutter】合并多个流Stream

1.说明 无意间发现了一个好用的库rxdart,它为 Dart 的 Stream 添加了额外的功能。 2.功能 (1)合并多个流Stream 借助Rx.combineLatest2()合并两个流stream1和stream2。 注意:如果dart文件中同时使用了getx,需要隐…

腾讯云视立方Electron 相关问题

安装相关 trtc-electron-sdk 是否兼容官方 Electron v12.0.1 版本? 兼容的,trtc-electron-sdk 没有特别依赖 elecron 自身的 SDK,所以没有相关的版本依赖。 Electron 下载慢甚至卡住不动? 当开始下载tmp-3320-1-SHASUMS256.txt-6.1.9文件…

【c语言——指针详解(4)】

文章目录 一、回调函数是什么?二、qsort的使⽤1、使⽤qsort函数排序整型数据2、使⽤qsort排序结构数据 三、qsort函数的模拟实现 作者主页 一、回调函数是什么? 回调函数就是⼀个通过函数指针调⽤的函数。 如果你把函数的指针(地址&#xf…

【进阶OpenCV】 (12)--人脸检测识别

文章目录 人脸识别一、获取分类器二、代码实现1. 图片预处理2. 加载人脸检测分类器3. 检测人脸4. 标注人脸 总结 人脸识别 要实现人脸识别首先要判断当前图像中是否出现了人脸,这就是人脸检测。只有检测到图像中出现了人脸,才能据此判断这个人到底是谁。…