当前位置: 首页 > news >正文

【Redis】持久化

对于Redis中间件来说,一般是作为内存型数据库或者缓存出现的。但是由于其数据是在内存中,因此当Redis所在的主机宕机之后,数据就会消失,再次重启之后,没有任何数据。这对于生产环境来说,是属于P0级别的灾难了。

因此,对于Redis来说,不仅要将数据存在内存中,还要将数据持久化到硬盘上。这样当Redis重启之后,可以通过硬盘中的数据来恢复内存中的数据。如果Redis是作为内存数据库的话,那么客户端就可以继续进行访问得到数据;如果Redis是作为缓存的话,那么就可以减少MySQL的压力,从而避免MySQL宕机。

Redis有两种持久化方式:RDBAOF

 RDB

RDB是定期备份的持久化方式,即Redis定期会把内存中的数据进行备份,生成一个快照,保存在硬盘中。这样,当Redis重启的时候,就可以读取RDB文件来恢复内存数据。

触发方式

手动触发

程序猿在客户端输入特定的命令,来触发Redis服务器快照的生成。

save:通过save命令,可以使Redis服务器触发快照行为,进行备份

bgsave:通过bgsave命令,同样可以使Redis触发快照行为,进行备份。

对于save和bgsave两个命令来说,最大的区别就是save会和其他客户端命令一样,在同一个进程中执行,因此就会影响其他客户端命令的执行;而对于bgsave命令来说,并不会在当前进程中执行,而是fork一个子进程,在子进程中执行,这样就不会影响其他客户端的请求。

 bgsave的执行流程

f38d4f7ba88551f981b4f6b28fcd6a34.png

1.  客户端发送bgsave命令之后,Redis服务器会判断是否已经正在执行该命令。如果正在执行,那么就会直接进行返回。

2. 如果没有执行,那么Redis服务器就会通过fork命令,来创建出一个子进程。

fork命令是Linux系统提供的一个创建子进程的API。简单来说,fork命令就是将原来的进程给简单粗暴的复制一份。复制完成之后,两个进程之间就没有任何的关系,各自会执行各自的内容,不过由于后续的进程,即子进程是父进程复制而来,因此两个进程中的数据是完成相同的。这样,让子进程生成一份快照,就相当于让父进程生成一份快照。

对于fork命令来说,是不是有比较大的性能开销?不会,执行fork命令进行内存拷贝的时候,并不是在内存空间中把所有的数据全部复制一份,而是采用写时拷贝的方式来完成。

所谓写时拷贝,当父子进程的数据是完成相同时,两者指向的内存空间还是同样的位置。但是当任一进程发生改变时,才会开辟一个新的内存空间来记录变化的数据。

综上所述,使用fork命令生成父子进程时,并不会产生较大的性能开销。毕竟Redis改变的数据并不是大多数,而是一小部分,因此对于写时拷贝来说消耗并不是很大,整体来说较快。

3. 父进程继续执行客户端的其他命令请求,而子进程则是来生成快照,进行备份。

4. 子进程持久化完成之后,就会来通知父进程。父进程再更新一些统计信息之后,子进程就可以销毁了。

自动触发

1. 在Redis的配置文件中可以进行配置,以来达到自动触发定期快照的操作;

2. 在主从模式中,给主节点加从节点时,主节点会主动生成快照,发送给从节点;

3. 当客户端发送shutdown命令,进程关闭服务器时,会触发快照的生成,但是如果是意外宕机,例如掉电或者kill,那么此时就不会生成快照。

RDB文件

1. RDB文件的存放位置,是可以通过Redis的配置信息来设置的,默认是放在/var/lib/redis中。

261d3dc54f8b4842b16bf95c874176b3.png

2. Redis文件是一个二进制的文件。即把内存中的数据通过压缩的形式,保存到这个二进制文件中。通过压缩,可以节省空间,但是进行操作时就会消耗一定的CPU资源。

3. Redis重启时,就会通过RDB文件来恢复内存中的数据。但是如果RDB的数据内容发生了变化,那么就有可能重启失败,也有可能重启成功。因此,Redis还专门提供了检查RDB文件的工具,可以在重启服务器之前,先检查RDB文件是否发生错误。

4. 在快照生成RDB文件时,会将生成的这些内容存储到一个临时的文件中。当快照生成完毕,就会使用新生成的RDB文件来代替旧的RDB文件,这样硬盘中自始至终就只有一个文件了。

 5. 在bgsave命令的执行流程中,虽然fork子进程的性能消耗并不大,但是RDB文件的生成也有一个较高的性能开销,因此RDB文件不是实时备份,而是定期备份。正是由于定期备份,因此在一次备份完成之后,Redis宕机,再次重启时,备份之后操作的数据都不复存在。

RDB特点

1. RDB文件是一个二进制格式的文件,因此非常适合用于备份、全量复制等场景。

2. Redis加载RDB恢复数据往往比加载AOF恢复数据要快。这是因为RDB使用二进制来组织数据,而AOF则是使用文本格式来组织数据,而计算机天然对二进制好感度高。

3. Redis无法做到实时持久化,毕竟生成一次快照消耗的资源还是较多的,属于重量级操作,频繁执行成本过高。

4. RDB使用二进制格式保存,但是Redis不同的版本可能二进制格式略有不同,因此可能存在兼容性问题(例如将5版本的RDB放到7版本的RDB文件中,就可能运行不起来)。

AOF

AOF(Append Only File)是实时备份的持久化方式。所谓实时备份,并不是将Redis服务器内存中的数据进行持久化,而是把用户进行的操作当作日志记录成文件。也就是说,当用户执行某条操作时,Redis就会进行记录,并且写入到文件中。这样,当Redis服务器重新启动的时候,就回去读取AOF文件,用来恢复数据。

对于RDB方式的持久化来说,最大的问题是不能实时持久化来保存数据。这就导致在某些突发情况发生后,Redis服务器重启时,Redis内存中的数据可能会存在丢失的情况。

因此,AOF方式的持久化,就是用来解决RDB存在的问题。当开启AOF方式的持久化之后,Redis服务器重新启动时,就会读取AOF文件中的内容来恢复内存数据,不会再读取RDB文件的内容。

 开启AOF

默认情况下,Redis服务器是使用RDB的方式来进行持久化的。对于AOF来说,默认则是关闭状态,要想使用AOF,就要在配置文件中进行开启:

 当AOF方式的持久化开启之后,RDB就会失效。并且对于AOF来说,其文件生成的位置和RDB文件生成的位置在同一目录下。

AOF与Redis性能间的关系

引入AOF之后,既要操作内存(Redis服务器需要对客户端发送的请求进行响应),又要操作硬盘(Redis服务器需要把客户端的操作当成日志写入文件),这是否对Redis的效率产生了很大的影响?答案是没有。

AOF虽然是把客户端的操作给记录下来,但是并不是直接让工作线程把数据给写入硬盘。而是先把数据写入到内存中的缓冲区中,当积累一定数量之后(通过积累,可以降低写硬盘的次数,从而减少性能的消耗),统一写入硬盘(写入硬盘时,采用了顺序读取的方式,相对随机读取来说还是比较快的一种读取方式)。

通过上述描述,我相信大家存在一个疑惑:把数据写入缓冲区,那不还是在内存中,这些数据依然有丢失的风险,因此AOF依旧没解决RDB存在的问题。

其实不然,AOF的确解决了RDB存在的不能实时持久化的问题,这本质上存在一个可靠和性能的矛盾性。当数据特别可靠时,其性能一定会有所损耗;当性能非常好时,其数据可靠性就会有所下降。例如MySQL中的隔离级别,当隔离级别是可串行化时,其数据基本上完全可靠,但是性能低下;当隔离级别是读未提交时,其读取到的数据不一定可靠,但是其性能一定非常高。

综上,针对Redis的AOF来说,其官方也给出了不同的措施来解决不同业务场景下的问题,即程序员根据对系统的评估来取舍缓存区的刷新策略。刷新频率越高,那么其性能影响也就越大,但是其数据的可靠性就越高;刷新频率越低,性能影响就会越小,但是数据的可靠性就会降低。

在Redis中,使用appendfsync属性来配置刷新策略,并且给出了三个配置值。

可配置值说明性能与可靠性
always

客户端进行操作之后,数据进入缓存区之后,直接写入AOF文件中。

性能最低,可靠性最高。

everysec

客户端进行操作之后,先写入缓冲区,然后每秒写入一次文件。

性能适中,可靠性适中。

Redis默认此刷新策略。

no

客户端进行操作之后,先写入缓存区,然后根据操作系统来控制写入文件。

性能最高,可靠性最低。

重写机制

在AOF文件中,记录的是客户端每次进行的操作。但是在客户端操作的过程中,可能某个变量会重复被操作,最后被删除。这些操作如果记录在AOF文件中,那么在Redis服务器重启的时候,也会对这个变量进行反复操作,最后删除,那么就是消耗大量内存但是做了无用的事。

因此Redis就存在一个机制,能够对AOF文件进行整理操作,这个整理就能够剔除其中的冗余操作,并且合并一些操作,达到给AOF文件瘦身的效果。这样,当Reids服务器进行重启的时候,就不会机械性的做一些无用的操作。

这个机制就被称为Redis的重写机制。

触发方式

手动触发和自动触发两种。

手动触发使用bgrewriteaof命令进行操作;

自动触发则根据auto-aof-rewrite-min-size和auto-aof-rewrite-percentage参数确定自动触发时机,auto-aof-rewrite-min-size表示触发重写时AOF的最小文件大小,默认是64MB,auto-aof-rewrite-percentage代表当前AOF占用大小相比较上次重写时增加的比例。

重写流程

① 当Redis接收到了重写操作时,就会fork一个子进程。如果此时Redis服务器已经在重写,那么就不会再次执行命令,直接返回。

 ② 父进程仍然接收请求,子进程负责针对AOF文件进行重写。在重写的时候,并不关心AOF文件原来有啥内容,只关心此时内存中数据的最终状态。因此,子进程只需要把当前的数据获取出来,以AOF文件的格式写入到一个新的AOF文件中。

③ 子进程在重写AOF文件的同时,父进程还是会不停的接收客户端的请求,并且把这些请求产生的AOF数据写入到缓冲区中,再刷新到原来的AOF文件中。在执行这些命令的同时,父进程还会准备一个新的缓冲区,把fork之后产生的AOF数据放入其中。

为啥要准备这个新的缓冲区?

当fork之后,子进程中的内存数据是父进程fork之前的,因此对于fork之后的请求对内存造成的修改,子进程是不知道的。所以,当Redis把子进程的内存数据整理完毕之后,如果直接代替之前的文件,那么整理文件过程中产生的数据会丢失。所以,要准备这个缓冲区来接收fork之后的一些请求。

④ 子进程整理完毕之后,会通知父进程,父进程把新缓冲区中的内容加入到新AOF文件之中,就可以用新的文件来代替旧的AOF文件。

当在重写过程中,发现Redis正在备份。那么此时,AOF重写就会停止,等待RDB快照完成,再继续进行重写的操作。

混合持久化

对于RDB来说,是没法做到实时备份,存在数据丢失的风险;对于AOF来说,是使用文本的格式来写入数据,导致后续加载文件的成本较高。

由于RBD和AOF各有优缺点,因此就又有了混合持久化的方式。正所谓,小孩子才做选择,大人全都要。简单来说,混合持久化就是对于每一个操作,都会使用AOF的方式来写入文件;当执行重写操作时,就会把当前内存的状态按照RDB的格式写入到新的AOF文件中。这样,即可以保证所有数据的及时更新,又可以在读取文件时采用较小的成本。

相关文章:

【Redis】持久化

对于Redis中间件来说,一般是作为内存型数据库或者缓存出现的。但是由于其数据是在内存中,因此当Redis所在的主机宕机之后,数据就会消失,再次重启之后,没有任何数据。这对于生产环境来说,是属于P0级别的灾难…...

港股指数实时行情API接口

港股 指数 实时 行情 API接口 # Restful API https://tsanghi.com/api/fin/index/HKG/realtime?token{token}&ticker{ticker}指定指数代码,获取该指数的实时行情(开、高、低、收、量)。 更新周期:实时。 请求方式&#xff1a…...

Qt5开发实战_图形_QPen

Qpen是Qt框架中的一个类,用于定义绘制线条的属性,包括颜色、宽度、样式、端点样式和连接样式。 具体属性(设置颜色和设置宽度直接pass从样式开始): 设置样式: pen的样式主要有以下几种: 分别是:直线样式…...

linux进程周边知识——内核对硬件的管理——计算机世界的管理

前言:本节主要讲解内核也就是操作系统对于硬件的管理, 本节内容同样为进程的周边知识。 主要是关于软件方面, 和我的上一篇——冯诺依曼体系结构可以说是兄弟文章, 这篇文章主要是关于硬件方面。 两篇文章都是为学习进程做准备。但…...

同声传译语音合成接口,分段预合成实现丝滑的衔接效果

背景: 在使用微信官方语音合成插件的时候遇到一个问题,textToSpeech这个api的内容限制在官网的文档上明明是1000个字节,也就是说能保证333个中文字符应该是没有问题的,但是也不知道为什么我这里仅仅传了150个中文字符就报错了&…...

数据结构——单链表详解(超详细)(1)

前言: 小编在近日学习了单链表的知识,为了加强记忆,于是诞生了这一篇文章,单链表是数据结构比较重要的知识,读者朋友们一定要去好好的学习!这个可以说是比顺序表更好用的线性表,下面废话不多说&…...

在 Linux 上使用 lspci 命令查看 PCI 总线硬件设备信息

lspci 命令用于显示 Linux 系统上的设备和驱动程序 当在个人电脑或服务器上运行 Linux 时,有时需要识别该系统中的硬件。lspci 命令用于显示连接到 PCI 总线的所有设备,从而满足上述需求。该命令由 pciutils 包提供,可用于各种基于 Linux 和…...

python数据可视化(6)——绘制散点图

课程学习来源:b站up:【蚂蚁学python】 【课程链接:【【数据可视化】Python数据图表可视化入门到实战】】 【课程资料链接:【链接】】 Python绘制散点图查看BMI与保险费的关系 散点图: 用两组数据构成多个坐标点,考察…...

【人工智能】Transformers之Pipeline(二):自动语音识别(automatic-speech-recognition)

​​​​​​​ 目录 一、引言 二、自动语音识别(automatic-speech-recognition) 2.1 概述 2.2 技术原理 2.2.1 whisper模型 2.2.2 Wav2vec 2.0模型 2.3 pipeline参数 2.3.1 pipeline对象实例化参数​​​​​​​ 2.3.2 pipeline对象使用参数…...

Mysql-错误处理: Found option without preceding group in config file

1、问题描述 安装MYSQL时,在cmd中“初始化”数据库时,输入命令: mysqld --initialize --consolecmd报错: D:\mysql-5.7.36-winx64\bin>mysql --initialize --console mysql: [ERROR] Found option without preceding group …...

[iOS]内存分区

[iOS]内存分区 文章目录 [iOS]内存分区五大分区栈区堆区全局区常量区代码区验证内存使用注意事项总结 函数栈堆栈溢出栈的作用 参考博客 在iOS中,内存主要分为栈区、堆区、全局区、常量区、代码区五大区域 还记得OC是C的超类 所以C的内存分区也是一样的 iOS系统中&a…...

sklearn基础教程:掌握机器学习入门的钥匙

sklearn基础教程:掌握机器学习入门的钥匙 在数据科学和机器学习的广阔领域中,scikit-learn(简称sklearn)无疑是最受欢迎且功能强大的库之一。它提供了简单而高效的数据挖掘和数据分析工具,让研究人员、数据科学家以及…...

【unity实战】使用unity制作一个红点系统

前言 注意,本文是本人的学习笔记记录,这里先记录基本的代码,后面用到了再回来进行实现和整理 素材 https://assetstore.unity.com/packages/2d/gui/icons/2d-simple-ui-pack-218050 框架: RedPointSystem.cs using System.…...

开发指南046-机构树控件

为了简化编程&#xff0c;平台封装了很多前端组件。机构树就是常用的组件之一。 基本用法&#xff1a; import QlmOrgTree from /qlmcomponents/tree/QlmOrgTree <QlmOrgTree></QlmOrgTree> 功能&#xff1a; 根据权限和控制参数显示机构树。机构树数据来源于核…...

SpringBatch文件读写ItemWriter,ItemReader使用详解

SpringBatch文件读写ItemWriter&#xff0c;ItemReader使用详解 1. ItemReaders 和 ItemWriters1.1. ItemReader1.2. ItemWriter1.3. ItemProcessor 2.FlatFileItemReader 和 FlatFileItemWriter2.1.平面文件2.1.1. FieldSet 2.2. FlatFileItemReader2.3. FlatFileItemWriter 3…...

如何评估AI模型:评估指标的分类、方法及案例解析

如何评估AI模型&#xff1a;评估指标的分类、方法及案例解析 引言第一部分&#xff1a;评估指标的分类第二部分&#xff1a;评估指标的数学基础第三部分&#xff1a;评估指标的选择与应用第四部分&#xff1a;评估指标的局限性第五部分&#xff1a;案例研究第六部分&#xff1a…...

程序员学CFA——经济学(七)

经济学&#xff08;七&#xff09; 汇率外汇市场外汇市场的功能外汇市场的参与者卖方买方 汇率的计算汇率报价基础货币与计价货币直接报价与间接报价外汇报价习惯 名义汇率和实际汇率货币的升值与贬值交叉汇率计算即期汇率与远期汇率即期汇率与远期汇率的概念远期升水/贴水远期…...

imx335帧率改到10fps的方法

验证: imx335.c驱动默认的帧率是30fps,要将 IMX335 的帧率更改为 10fps,需要调整与帧率相关的参数。FPS(frames per second,每秒帧数)通常由 sensor 的曝光时间(exposure time)和垂直总时间(VTS,Vertical Total Size)共同决定。VTS 定义了 sensor 完成一帧图像采集…...

Large Language Model系列之二:Transformers和预训练语言模型

Large Language Model系列之二&#xff1a;Transformers和预训练语言模型 1 Transformer模型 Transformer模型是一种基于自注意力机制的深度学习模型&#xff0c;它最初由Vaswani等人在2017年的论文《Attention Is All You Need》中提出&#xff0c;主要用于机器翻译任务。随…...

java后端项目启动失败,解决端口被占用问题

报错信息&#xff1a; Web server failed to start . Port 8020 was already in use. 1、查看端口号 netstat -ano | findstr 端口号 2、终止进程 taskkill /F /PID 进程ID 举例&#xff1a;关闭8020端口...

PostgreSQL安装/卸载(CentOS、Windows)

说明&#xff1a;PostgreSQL与MySQL一样&#xff0c;是一款开源免费的数据库技术&#xff0c;官方口号&#xff1a;The World’s Most Advanced Open Source Relational Database.&#xff08;世界上最先进的开源关系数据库&#xff09;&#xff0c;本文介绍如何在Windows、Cen…...

OutOfMemoryError异常OOM排查

目录 参考工具MAT(Memory Analyzer)一、产生原因二、测试堆溢出 java.lang.OutOfMemoryError: Java heap space测试代码运行手动导出dump文件mat排查打开dump文件查看Leak Suspects(泄露疑点)参考 【JVM】八、OOM异常的模拟 MAT工具分析Dump文件(大对象定位) 用arthas排…...

【Python】Arcpy将excel点生成shp文件

根据excel点经纬度数据&#xff0c;生成shp&#xff0c;参考博主的代码&#xff0c;进行了修改&#xff0c;在属性表中保留excel中的数据。 参考资料&#xff1a;http://t.csdnimg.cn/OleyT 注意修改以下两句中的数字。 latitude float(row[1]) longitude float(row[2])imp…...

torch之从.datasets.CIFAR10解压出训练与测试图片 (附带网盘链接)

前言 从官网上下载的是长这个样子的 想看图片&#xff0c;咋办咧&#xff0c;看下面代码 import torch import torchvision import numpy as np import os import cv2 batch_size 50transform_predict torchvision.transforms.Compose([torchvision.transforms.ToTensor(),…...

什么ISP?什么是IAP?

做单片机开发的工程师经常会听到两个词&#xff1a;ISP和IAP&#xff0c;但新手往往对这两个概念不是很清楚&#xff0c;今天就来和大家聊聊什么是ISP&#xff0c;什么是IAP&#xff1f; 一、ISP ISP的全称是&#xff1a;In System Programming&#xff0c;即在系统编程&…...

外卖霸王餐系统怎么快速盈利赚钱?

微客云外卖霸王餐系统&#xff0c;作为近年来外卖行业中的一股新兴力量&#xff0c;以其独特的商业模式和营销策略&#xff0c;迅速吸引了大量消费者的目光。该系统通过提供显著的折扣和返利&#xff0c;让顾客能够以极低的价格甚至免费享受到美味的外卖&#xff0c;同时&#…...

Linux环境下安装Nodejs

Linux环境下安装Nodejs 下载地址&#xff1a;https://nodejs.org/zh-cn/download/package-manager 一、使用压缩包自定义安装 上述链接下载好对应版本的软件包后&#xff0c;我存放到 /evn/nodejs 目录下&#xff08;根据自己实际情况设置&#xff09; 设置软链接 sudo ln…...

【Rust】字符串String类型学习

什么是String Rust的核心语言中只有一个String类型&#xff0c;那就是String slice,str通常被当作是&str的借用。String类型是通过标准库提供的&#xff0c;而不是直接编码到核心语言中&#xff0c;它是一个可增长的、可变的、utf-8编码的类型。str和String都是utf-8编码的…...

先验概率 后验概率 最大似然估计 自编码器AE

先验概率 先验概率&#xff1a;由因求果中的因 作用&#xff1a;后验概率是比较难以计算的&#xff0c;我们通常使用贝叶斯公式由先验概率计算后验概率。 贝叶斯公式&#xff1a;P(B|A)P(A|B)P(B)/P(A)&#xff0c;其中P(B|A)为后验概率&#xff0c;P(A|B)为先验概率。 后验…...

qt 鼠标接近某线时,形状变化举例

1.qt 鼠标接近某线时&#xff0c;形状变化举例 在Qt中&#xff0c;要实现鼠标接近某条线时形状发生变化的效果&#xff0c;你需要利用QWidget的enterEvent和leaveEvent&#xff0c;或者更通用的mouseMoveEvent来检测鼠标的位置&#xff0c;并相应地改变鼠标的光标形状。 以下…...