【Redis】Redis的持久化(备份)

news2024/11/19 7:33:16

【Redis】Redis的持久化(备份)

Redis的数据全部在内存里,如果突然宕机,数据就会全部丢失,因此必须有一种机制来保证Redis的数据不会因为故障而丢失,这种机制就是Redis的持久化机制。

如图所示,Redis的持久化机制有两种:

  • 快照(snapshotting),它是备份当前时间节点Redis在内存中的数据记录。
  • 只追加文件(Append-OnlyFile,AOF),其作用就是当Redis执行写命令后,在一定的条件下将执行过的写命令依次保存在Redis的备份文件中,将来就可以依次执行那些被保存的命令恢复Redis的数据了。

在这里插入图片描述

快照是一次全量备份,AOF日志是连续的增量备份

快照是内存数据的二进制序列化形式,在存储上非常紧凑,而AOF日志记录的是内存数据修改的指令记录文本。AOF日志在长期的运行过程中会变得无比庞大,数据库重启时需要加载AOF日志进行指令重放,这个时间就会无比漫长,所以需要定期进行AOF重写,给AOF日志进行瘦身。

对于快照备份,如果当前Redis的数据量大备份这个快照文件时可能造成Redis卡顿,但是它的优点是恢复和重启速度比较快,对于AOF备份,它只是追加写入命令,备份代价较小,所以备份一般不会造成Redis卡顿,但是恢复重启要执行更多的命令,备份文件可能也很大。两种备份的方式都有各自的优缺点,在Redis中快照备份是必备的,AOF备份则是可选的,当然我们也可以同时使用快照备份和AOF备份。下面我们来详细讲解它们的内容。

RDB(快照)持久化

RDB(快照)备份是Redis默认开启的备份方式。我们打开配置文件redis.conf,可以看到以下默认配置:

################SNAPSHOTTING################
# 在900s(15分钟)内存在1个key改变,则执行备份
save 900 1
# 在300s(6分钟)内存在10个key改变,则执行备份
save 300 10
# 在60s(1分钟)内存在1000个key改变,则执行备份
save 60 10000
# 后台备份运行出错时停止Redis的写入命令
stop-writes-on-bgsave-error yes
# 是否压缩备份的RDB文件
rdbcompression yes
# RDB(快照)备份文件名称
dbfilename dump.rdb
# 是否检验RDB备份文件
rdbchecksum yes
# 备份文件路径
dir ./

首先看save的三个配置:

save 900 1
save 300 10
save 60 10000

Redis会在一定情况下备份数据,配置save后面的两个整数分别是时间(单位:s)key的改变数量。这里要考虑的是触发备份的频率,如果太密集了,备份就多了,会影响到系统的性能:如果很少备份,就有可能丢失数据。这是大家在配置的时候需要注意的地方。

stop-writes-on-bgsave-error yes

这个配置项是让Redis在备份失败时,停止写入命令,这样就可以让运维或者开发者注意到发生的问题了。至于其他的配置,在注释中也交代得比较清晰了,这里不再赘述。

RDB(快照)原理

​ 我们知道Redis是单线程程序,这个线程要同时负责多个客户端套接字的并发读写操作和内存数据结构的逻辑读写。

​ 在服务线上请求的同时,Redis还需要进行内存快照,内存快照要求Redis必须进行文件IO操作,可文件IO操作不能使用多路复用API。

​ 这意味着单线程在服务线上请求的同时,还要进行文件IO操作,而文件IO操作会严重拖累服务器的性能。

​ 还有个重要的问题,为了不阻塞线上的业务,Redis就需要一边持久化,一边响应客户端的请求。持久化的同时,内存数据结构还在改变,比如一个大型的hash字典正在持久化,结果一个请求过来把它给删掉了,可是还没持久化完呢,这该怎么办呢?

Redis使用操作系统的多进程COw(CopyOnWrite)机制来实现快照持久化,这个机制很有意思,也很少人知道。多进程COW也是鉴定程序员知识广度的一个重要指标。

fork(多进程)

​ Redis在持久化时会调用glibc的函数fork产生一个子进程,快照持久化完全交给子进程来处理,父进程继续处理客户端请求。子进程刚刚产生时,它和父进程共享内存里面的代码段和数据段。这时你可以把父子进程想象成一个连体婴儿,它们在共享身体。这是Linux操作系统的机制,为了节约内存资源,所以尽可能让它们共享起来。在进程分离的一瞬间,内存的增长几乎没有明显变化。

​ 子进程做数据持久化,不会修改现有的内存数据结构,它只是对数据结构进行遍历读取,然后序列化写到磁盘中。但是父进程不一样,它必须持续服务客户端请求然后对内存数据结构进行不间断的修改。

​ 这个时候就会使用操作系统的COW机制来进行数据段页面的分离。如图所示,数据段是由很多操作系统的页面组合而成,当父进程对其中一个页面的数据进行修改时,会将被共享的页面复制一份分离出来,然后对这个复制的页面进行修改。这时子进程相应的页面是没有变化的,还是进程产生时那一瞬间的数据。

在这里插入图片描述

​ 随着父进程修改操作的持续进行,越来越多的共享页面被分离出来,内存就会持续增长,但是也不会超过原有数据内存的2倍大小。另外,Redis实例里冷数据占的比例往往是比较高的,所以很少会出现所有的页面都被分离的情况,被分离的往往只有其中一部分页面。每个页面的大小只有4KB,一个Redis实例里面一般都会有成千上万个页面。

​ 子进程因为数据没有变化,它能看到的内存里的数据在进程产生的一瞬间就凝固了,再也不会改变,这也是为什么Redis的持久化叫"快照"的原因。接下来子进程就可以非常安心地遍历数据,进行序列化写磁盘了。

RDB持久化的优点RDB持久化的缺点
1.只有一个文件dumprdb(默认文件名为dump.rdb,可自定义),方便持久化1.可能有数据丢失,不适合对高可用要求比较高的场景在两次RDB持久化的时间间隔中,系统一旦出现宕机则这段时间内的数据因没有写入磁盘都将丢失
2.容灾性好,一个文件可以保存到安全的磁盘2.由于RDB是通过Fork子进程来协助完成数据持化作的,因此,如果当数据集较大时,可能会导致整个服务器间歇性暂停服务
3.实现了性能最大化它Fork单独子进程来完成持久化,让主进程继续处理命令,主进程不进行任何IO操作以而保证了Redis的高性能
4.是一个紧凑压缩的二进制文件,Redis重启时的加载效率比AOF持久化更高,在数据量大时更加明显

AOF持久化

AOF备份并不是一个默认开启的方式,它以追加写入命令日志的方式备份,打开redis.config文件,可以看到如下内容:

################APPENDONLYMODE################
#是否使用AOF方式备份,默认为否(no),如果需要可以修改为yes
appendonly no

#AOF方式的备份文件名
appendfilename "appendonly.aof"

####AOF备份频率####
# 代表每次写入命令后立即追加到AOF文件中,该方式消耗资源最多,也最安全
# appendfsync always
# 代表以每秒执行1次AOE的方式备份,消耗资源较多,也有较低概率丢失数据
appendfsync everysec
# 将写入工作交给操作系统,由操作系统来判断缓冲区大小
# 统一写到AOF文件中(消耗资源少,但同步频率低,易丢数据)
# appendfsync no.....

# 当进行SNAPSHOTTING备份数据时,是否执行AOF备份方式,若为yes则停止
no-appendfsync-on-rewrite no

# 当AOF文件扩展时,文件大小按什么百分比扩展
auto-aof-rewrite-percentage 100
# 默认AOF文件最小64MB
auto-aof-rewrite-min-size 64mb
# 当通过AOF方式导入数据时,如果发现备份命令错误是否忽略
# 如果不忽略,遇到错误命令则停止恢复数据
aof-load-truncated yes

# 是否使用和RDB文件混合的方式备份,这是Redis4.0以上版本拥有的方式
aof-use-rdb-preamble yes

上述的中文注释比较清楚,这里需要理解的是配置项appendfsyn,它存在三个选置项:alwayseverysecno,关于它们的解释注释中已经讲解清楚了。我们需要注意的是使用always会比较消耗资源,性能也较差,但是不会丢失数据,安全度高;everysec则是每秒备份一次。

AOF日志存储的是Redis服务器的顺序指令序列,AOF日志只记录对内存进行修改的指令记录。

假设AOF日志记录了自Redis实例创建以来所有的修改性指令序列,那么就可以通过对一个空的Redis实例顺序执行所有的指令一一也就是“重放”,来恢复Redis当前实例的内存数据结构的状态。

Redis会在收到客户端修改指令后,进行参数校验、逻辑处理,如果没问题,就立即将该指令文本存储到AOF日志中,也就是说,先执行指令才将日志存盘。这点不同于leveldb、hbase等存储引擎,它们都是先存储日志再做逻辑处理。

Redis在长期运行的过程中,AOF的日志会越来越长。如果实例宕机重启,重放整个AOF日志会非常耗时,导致Redis长时间无法对外提供服务,所以需要对AOF日志瘦身。

Redis执行AOF持久化时会调用lushAppendOnlyFile函数,这个函数执行以下两个工作来写入保存。

  • write:根据条件将aof_buf中的缓存写入AOF文件
  • save:根据条件调用fsyncfdatasync函数,将AOF文件保存到磁盘中

AOF文件以日志的形式记录Redis服务端每一个写、删除操作,不包括查询操作。记录内容是Redis通信协议(RESP)格式的命令文本。RESP是Redis客户端和服务端之前使用的一种通信议,RESP实现简单、快速解析、可读性好。

AOF重写

Redis提供了bgrewriteaof指令用于对AOF日志进行瘦身,其原理就是开辟一个子进程对内存进行遍历,转换成一系列Redis的操作指令,序列化到一个新的AOF日志文件中。序列化完毕后再将操作期间发生的增量AOF日志追加到这个新的AOF日志文件中,追加完毕后就立即替代旧的AOF日志文件了,瘦身工作就完成了。

fsync

AOF日志是以文件的形式存在的,当程序对AOF日志文件进行写操作时,实际上是将内容写到了内核为文件描述符分配的一个内存缓存中,然后内核会异步将脏数据刷回到磁盘的。

这就意味着如果机器突然宕机,AOF日志内容可能还没有来得及完全刷到磁盘中,这个时候就会出现日志丢失。那该怎么办?

Linux的glibc提供了fsync(intfd)函数可以将指定文件的内容强制从内核缓存刷到磁盘。只要Redis进程实时调用fsync函数就可以保证AOF日志不丢失。但是fsync是一个磁盘IO操作,它很慢!如果Redis执行一条指令就要fsync一次,那么Redis高性能的地位就不保了。

所以在生产环境的服务器中,Redis通常是每隔1s左右执行一次fsyn操作,这个1s的周期是可以配置的。这是在数据安全性和性能之间做的一个折中,在保持高性能的同时,尽可能使数据少丢失。

Redis同样也提供了另外两种策略,一个是永不调用fsync一让操作系统来决定何时同步磁盘,这样做很不安全,另一个是来一个指令就调用fsync一次一-结果导致非常慢。这两种策略在生产环境中基本不会使用,了解一下即可。

AOF持久化的优点AOF持久化的缺点
1.实时持久化,数据安全,AOF持久化可以配置appendfsync属性为always,每进行一次命令操作就记录到AOF文件中一次,这样数据最多丢失一次(推荐并且也是默认的措施为每秒fsync一次,这种fsync策略可以兼顾速度和安全性)1.AOF持久化文件通常比RDB持久化文件大很多
2.它通过Append模式写文件,即使中途服务器宕机,也可以通过Redis-check-aof工具解决数据一致性问题2.比RDB持久化启动效率低,数据集大时较为明显
3.AOF机制的Rewrite模式。AOF文件过大触碰到临界点时,Rewrite模式会被运行,重写内存中的所有数据,从而大大缩小文件体积3.AOF文件体积可能迅速变大,需要定期执行重写操作来降低文件体积

运维

快照是通过开启子进程的方式进行的,它是一个比较耗资源的操作

  1. 遍历整个内存,大块写磁盘会加重系统负载
  2. AOF的fsync是一个耗时的IO操作,它会降低Redis性能,同时也会增加系统IO负担。

所以通常Redis的主节点不会进行持久化操作,持久化操作主要在从节点进行从节点是备份节点,没有来自客户端请求的压力,它的操作系统资源往往比较充沛。

但是如果出现网络分区,从节点长期连不上主节点,就会出现数据不一致的问题,特别是在网络分区出现的情况下,主节点一旦不小心宕机了,那么数据就会丢失,所以在生产环境下要做好实时监控工作,保证网络畅通或者能快速修复。另外还应该再增加一个从节点以降低网络分区的概率,只要有一个从节点数据同步正常数据也就不会轻易丢失。

RDB-AOF混合持久化

重启Redis时,我们很少使用rdb来恢复内存状态,因为会丢失大量数据。我们通常使用AOF日志重放,但是重放AOF日志相对于使用rdb来说要慢很多,这样在Redis实例很大的时候,启动需要花费很长的时间。

Redis4.0为了解决这个问题,带来了一个新的持久化选项一混合持久化。如图所示,将rdb文件的内容和增量的AOF日志文件存在一起。这里的AOF日志不再是全量的日志,而是自持久化开始到持久化结束的这段时间发生的增量AOF日志,通常这部分AOF日志很小。

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-krqWiEVz-1692199659371)(C:\Users\HUAWEI\AppData\Roaming\Typora\typora-user-images\image-20230816231647272.png)]

于是在Redis重启的时候,可以先加载rdb的内容,然后再重放增量AOF日志就可以完全替代之前的AOF全量文件重放,重启效率因此得到大幅提升。

件存在一起。这里的AOF日志不再是全量的日志,而是自持久化开始到持久化结束的这段时间发生的增量AOF日志,通常这部分AOF日志很小。

在这里插入图片描述

于是在Redis重启的时候,可以先加载rdb的内容,然后再重放增量AOF日志就可以完全替代之前的AOF全量文件重放,重启效率因此得到大幅提升。

开启混合模式,将aof-use-rdb-preamble参数值设置为yes便可。

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

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

相关文章

将单个训练数据集文件拆分为:image文件和label文件(pytorch学习+蚂蚁蜜蜂数据集)

蚂蚁蜜蜂分类数据集下载链接:https://download.pytorch.org/tutorial/hymenoptera_data.zip 要实现如图操作: 将ants分为ants_image和ants_label 将bees分成bees_image和bees_label 创建ants_label和bees_label,并且以图片名作为txt文件的…

layui单选必填验证

效果&#xff1a; 代码 <div class"layui-form-item"><label class"layui-form-label layui-required-title">对此次活动内容输出是否满意&#xff1f;</label><div class"layui-input-block"><input type"ra…

int(M)、char(M) 、varchar(M)的用法

文章目录 MySQL中int、char、varchar的一般用法1、int (M)2、varchar(M)3、char(M)4、char(M) 和varchar(M)的区别4.1 区别1&#xff1a;定长和变长4.2 区别2&#xff1a;存储容量上4.3 区别3&#xff1a;在展示上4.4 区别4&#xff1a;在使用场景上4.5 区别5&#xff1a;在书写…

如何编写技术文档?

软件开发中&#xff0c;为你的软件系统编写文档并不是一件新鲜的事情。几乎所有人都明白这样的道理&#xff1a; 你的软件产品如何优秀对用户来说并不是最重要的&#xff0c;因为你的文档如果不够优秀&#xff0c;用户不会使用它&#xff01;即便用户在某些情况下不得不使用你…

uniapp app 实现右上角回首页;点homeButton返回上一页;onNavigationBarButtonTap不生效问题

场景&#xff1a; app&#xff0c;Android移动端 实现点击右上角图标&#xff0c;回首页。 问题&#xff1a;用了官网的 homeButton&#xff0c;图标正常展示了&#xff0c;也可点击&#xff0c;但每次点击后是会返回上一页而非首页。 后来查到说&#xff0c;要结合onNavigatio…

SciencePub学术 | 计算机重点SCIE征稿中

SciencePub学术 刊源推荐: 计算机重点SCIE征稿中&#xff01;信息如下&#xff0c;录满为止&#xff1a; 一、期刊概况&#xff1a; 计算机语音类重点SCIE 【期刊简介】IF&#xff1a;4.0-4.5&#xff0c;JCR2区&#xff0c;中科院3区&#xff1b; 【出版社】世界排名前三出…

Mysql之explain详解

1. explain作用 使用explain可以展示出sql语句的执行计划&#xff0c;再根据sql的执行计划去判断这条sql有哪些点可以进行优化&#xff0c;从而让sql的效率达到最大化。 2. 执行计划各列含义 &#xff08;1&#xff09;id&#xff1a;id列是select的序列号&#xff0c;这个…

Docker基础入门:从0开始学习容器化技术

Docker基础入门&#xff1a;从零开始学习容器化技术 一、Docker基础1.1、Docker起源1.2、Docker概念1.3、Docker优势1.4、Docker 的组成 二、Docker安装2.1、卸载旧版Docker2.2、需要的安装包依赖2.3、设置镜像仓库2.4、更新yum软件包索引2.5、安装Docker--社区版2.6、配置镜像…

十、接口(2)

本章概要 抽象类和接口完全解耦多接口结合使用继承扩展接口 结合接口时的命名冲突 抽象类和接口 尤其是在 Java 8 引入 default 方法之后&#xff0c;选择用抽象类还是用接口变得更加令人困惑。下表做了明确的区分&#xff1a; 特性接口抽象类组合新类可以组合多个接口只能…

Java基础知识实际应用(学生信息管理系统、猜拳小游戏、打印日历)

一、Java学生信息管理系统 这个系统包含了添加、修改、删除、查询和显示所有学生信息等功能。您可以在此基础上进行修改和完善&#xff0c;以适应您的需求。 import java.util.Scanner;public class StudentManagementSystem {private static Scanner scanner new Scanner(S…

C++——oo的魅力之多态

文章目录 多态的概念多态的定义和实现多态的构成条件虚函数重写的两个例外协变(基类和派生类虚函数返回值类型不同)析构函数的重写(基类和派生类析构函数名字不同) c11 override 和 final关键字 重载&#xff0c;重写(覆盖)&#xff0c; 隐藏(重定义)对比抽象类(纯虚函数)多态的…

Vivado使用入门之二:网表物理约束

目录 一、背景 二、物理约束 2.1 概念 2.2 网表约束 2.2.1 CLOCK_DEDICATED_ROUTE 2.2.2 MARK_DEBUG 2.2.3 DONT_TOUCH 2.2.4 LOCK_PINS 三、位置约束 四、布线约束 4.1 route 4.2 assign routing mode 五、参考 一、背景 在工程设计中为了保证上板后功能正常&…

【BI看板】Docker-compose安装Superset,安装最新版本2.1.0

软件及环境准备 docker&#xff0c; docker-compose docker-compose安装 字节码安装 #wget https://github.com/docker/compose/releases/download/v2.5.0/docker-compose-linux-x86_64 #mv docker-compose-linux-x86_64 docker-compose #chmod x /usr/local/bin/docker-com…

一、计算机网络体系结构

Content 1. 计算机网络的组成2. 计算机网络的功能3. 计算机网络的分类4. 计算机网络的性能指标5. 计算机网络分层结构OSI模型TCP/IP模型互联网五层模型共同点&#xff1a; 6. 计算机网络提供的服务按三种方式分类面向连接服务和无连接服务可靠服务和不可靠服务有连接服务和无连…

5G+AI数字化智能工厂建设解决方案PPT

导读&#xff1a;原文《5GAI数字化智能工厂建设解决方案》&#xff08;获取来源见文尾&#xff09;&#xff0c;本文精选其中精华及架构部分&#xff0c;逻辑清晰、内容完整&#xff0c;为快速形成售前方案提供参考。数字化智能工厂定义 智能基础架构协同框架 - 端、边、云、网…

Java课题笔记~ SpringMVC拦截器

SpringMVC 中的 Interceptor 拦截器&#xff0c;它的主要作用是拦截指定的用户请求&#xff0c;并进行相应的预处理与后处理。其拦截的时间点在“处理器映射器根据用户提交的请求映射出了所要执行的处理器类&#xff0c;并且也找到了要执行该处理器类的处理器适配器&#xff0c…

2023华为产品测评官-开发者之声 + 华为云ModelArts试用体验心得

2023华为产品测评官&#xff0d;开发者之声 华为云ModelArts试用体验心得 文章目录 2023华为产品测评官&#xff0d;开发者之声 华为云ModelArts试用体验心得一、活动介绍二、华为云ModelArts简介三、AI Gallery简介步骤1&#xff1a;订阅模型步骤2&#xff1a;使用订阅模型部…

Reids 的整合使用

大家好 , 我是苏麟 , 今天带来强大的Redis . REmote DIctionary Server(Redis) 是一个由 Salvatore Sanfilippo 写的 key-value 存储系统&#xff0c;是跨平台的非关系型数据库。 Redis 是一个开源的使用 ANSI C 语言编写、遵守 BSD 协议、支持网络、可基于内存、分布式、可选…

冯·诺依曼计算机

一、定义 冯诺依曼机&#xff08;von Neumann machine&#xff09;&#xff0c;又称冯诺依曼计算机&#xff0c;根据冯诺依曼提出的存储程序概念设计的计算机。主要特征是&#xff1a;指令与数据都以二进制形式储存在存储器里&#xff1b;指令根据其储存的顺序执行。 冯…

SpringBoot常用注解 - @Controller

Controller : Controller是加在类上面的注解&#xff0c;使得类里面的每个方法都返回一个视图页面 实际开发中&#xff0c;有时候只是让后端的结果返回到前端&#xff0c;而不作为新的视图页面&#xff0c;此时需要结合 ResponseBody&#xff0c;让这个方法返回给前端的不是一个…