Redis 的持久化(真的好细)

前言

        Redis 是一个内存数据库,把数据存储在内存中,而内存中的数据是不持久的,要想数据持久就得将数据存储到硬盘中,而 Redis 相比于 Mysql 这样的关系型数据库最大的优势就在于将数据存储在内存中从而效率更高,速度更快

        所以小孩子才做选择,我全都要。Redis 为了保证效率和持久性,于是将一份数据同时存储到内存和硬盘中,有同学可能会疑惑,将数据同时存储到内存和硬盘效率不就低了吗?实际上将数据存储到硬盘有不同的策略,能够保证效率依然很高。

        当要查询某个数据时,就从内存中读取。而硬盘中的数据相当于是一个备份,当内存中的数据因为某些原因丢失后就可以通过硬盘恢复。

实现持久化的策略

        Redis ⽀持 RDBAOF 两种持久化机制。持久化功能有效地避免因进程退出造成数据丢失问题, 当下次重启时利⽤之前持久化的⽂件即可实现数据恢复。

        RDB:相当于定期备份,每隔一段规定时间,便对数据进行一次整体的备份

        AOF:相当于实时备份,每当 Redis 中更新了数据,便将数据进行备份

RDB

 .rdb 文件所在的路径

        通过 Redis 的配置文件 redis.conf 可以查看 .rdb 文件所在的路径

        可以看到 .rdb 文件默认存储在路径:

 cd /var/lib/redis

.rdb 文件的名称

          通过 Redis 的配置文件 redis.conf 可以查看 .rdb 文件的名称

        在上述的路径中我们就可以找到 dump.rdb 文件

        RDB 持久化是把当前进程数据生成快照保存到硬盘的过程。

        RDB 会定期的将内存中的数据生成快照保存到硬盘中,后续 Redis 一旦重启了(数据丢失了)就会根据硬盘中保存的快照来恢复数据

        在 RDB 机制中,备份数据的时机分为“手动触发” 和 “自动触发

手动触发

        程序员通过 Redis 客户端,执行特定的命令,来触发快照的生成,进行数据备份

sava 命令

        执行 sava 命令,Redis 会全力以赴的进行“快照生成”的操作,由于 Redis 是单线程,所以就会导致其他客户端的命令无法执行,造成阻塞。可能会导致严重的后果,所以一般不使用该命令

bgsave 命令

        Redis 进程执⾏ fork 操作创建⼦进程,RDB 持久化过程由⼦进程负责,完成后⾃动结束。阻塞只发⽣在 fork 阶段,⼀般时间很短。

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

bgsave 命令流程说明

        1.执⾏ bgsave 命令,Redis ⽗进程判断当前是否存在其他正在执⾏的⼦进程,如 RDB/AOF ⼦进程,如果存在(说明其他 Redis 客户端已经发起了备份数据的请求) bgsave 命令直接返回。

        2.⽗进程执⾏ fork 创建⼦进程,fork 过程中⽗进程会阻塞(但时间很短),fork 创建子进程的过程简单粗暴,直接把当前的进程复制一份作为子进程,子进程会复制父进程的 PCB,内存中的数据,文件描述符表等... ,所以子进程的内存中拥有和父进程一样的数据,所以安排子进程备份内存中的数据和备份父进程中的数据一样。

        有同学可能会想,子进程复制了父进程中的数据,如果父进程中的数据很多,那么复制出来的子进程也会占用内存中的大量资源。但其实不会!

        对于子进程和父进程中相同的数据,不会为子进程重新拷贝一份,而是让两个进程共同使用一份内存数据,只有子进程和父进程中的数据不同时,才会进行真正的数据拷贝。

        3.⽗进程 fork 完成后,bgsave 命令返回 "Background saving started" 信息并不再阻塞⽗进程,可以继续响应其他命令。

        4.⼦进程创建 RDB ⽂件,根据内存中的数据⽣成临时快照⽂件,完成后对原有⽂件进⾏替换。

        5.进程发送信号给⽗进程表示完成,⽗进程更新统计信息。

自动触发

        注意:RDB 文件在备份时会创建一个新的 RDB 文件来替换原来的文件

        通过 Redis 的配置文件 redis.conf 可以查看在达到何种条件时会自动触发 RDB 文件的备份。        

        save 900 1 代表在 900s 内进行了一次修改就进行备份,同理 save 300 10 代表在 300s 内进行了 10 次修改就进行备份

        我们可以修改上面的配置来控制自动备份的时机,但要注意一个原则:不能频繁的进行 RDB 文件的备份,因为备份一次 RDB 文件会造成较大的开销

        由于备份 RDB 文件不能太频繁,所以也导致 RDB 快照中备份的数据和实际 Redis 中的数据存在一定的偏差,如果在两次备份间 Redis 出现了问题导致数据丢失,就无法进行恢复。而 AOF 就是解决这个问题的方案

正常退出触发

        除了在达到时间和修改次数要求后进行自动备份,在 Redis 服务器正常关闭时也会触发 RDB 文件的自动备份

        但如果 Redis 服务器异常关闭,如 kill -9 杀死 Redis 服务器进程,或者服务器掉电,此时 Redis 服务器就来不及进行 RDB 文件的自动备份,在上次备份后所进行的操作就会丢失

主从复制触发

        Redis 进行主从复制时,主节点会自动的生成 RDB 快照,然后把 RDB 快照文件传给子节点,子节点就能根据 RDB 快照文件获取父节点中的数据

执行 flushall 命令

        执行 flushall 命令也会同步将 RDB 文件清空

RDB 文件损坏会怎样?

        这个问题首先要看 RDB 文件损坏在哪里,如果是将 RDB 文件的末尾改坏了(比如在文件末尾添加了一些数据)那么前面的内容不会受到影响,此时可以正常的启动 Rdis 服务器,也可以读出 RDB 文件中备份的正确数据

        但要是中间位置的数据被破坏,那么大概率 Redis 服务器无法正常启动(因为 Redis 服务器启动时会读取 RDB 文件中的内容),即使 Redis 服务器正常启动了,数据也大概率会有错误,此时数据是不可靠的。

检查 RDB 文件是否损坏

        那么在得到一个 RDB 文件时,我们就要考虑这个 RDB 文件是否有损坏,如果有损坏就不能使用,避免对 Redis 中原来的数据造成影响,我们该如何检查 RDB 文件是否损坏呢?

通过下述命令检查

redis-check-rdb /var/lib/redis/dump.rdb

        如图,当 RDB 文件有损坏时就会报错。

RDB 的优缺点

• RDB 是⼀个紧凑压缩的⼆进制⽂件,代表 Redis 在某个时间点上的数据快照。⾮常适⽤于备份,全量复制等场景。⽐如每 6 ⼩时执⾏ bgsave 备份,并把 RDB ⽂件复制到远程机器或者⽂件系统中 (如 hdfs )⽤于灾备。

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

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

• RDB ⽂件使⽤特定⼆进制格式保存,Redis 版本演进过程中有多个 RDB 版本,兼容性可能有⻛ 险。

AOF

        AOF 会将用户的每一步操作都保存到文件中,当 Redis 服务器重新启动的时候就会读取 AOF 文件中的内容来还原数据。

AOF 相关配置

        AOF 默认是关闭状态,可以通过修改 Redis 的配置文件来进行修改:

        如上图,appendonly 配置项决定了 AOF 是否开启,注意:当 AOF 开启后 RDB 便失效了,Redis 启动时只会读取 .aof 文件中的内容进行数据恢复。

        appendfilename 配置项决定了 .aof 文件的文件名,而 appendonly.aof 文件所在的位置和 .rdb 文件相同,在 /var/lib/redis

AOF 工作流程

1. 所有的写⼊命令会追加到 aof_buf(缓冲区)中。

2. AOF 缓冲区根据对应的策略向硬盘做同步操作。

3. 随着 AOF ⽂件越来越⼤,需要定期对 AOF ⽂件进⾏重写,达到压缩的⽬的。 

4. 当 Redis 服务器启动时,可以加载 AOF ⽂件进⾏数据恢复。

为什么需要 aof_buf(缓冲区)

        如果不使用缓冲区,每当用户传入一个命令就需要改变内存中数据的同时将命令写入到硬盘上的 .aof 文件中,这就说明,当 Redis 收到一百条命令就需要读写硬盘 100 次,频繁读取硬盘会造成严重的资源浪费。

        所以可以先将命令保存到缓冲区中,保存一批命令后再全部将其保存到硬盘中,这大大减少了读写硬盘的次数,提高了性能。

        问题:可能有同学会疑惑,如果缓冲区中的内容还没来得及保存到硬盘中,Redis 服务器就崩了,那缓冲区中的数据不就丢失了吗? 

        确实是这样,缓冲区中没来得及保存到硬盘的数据确实会丢失。但这也没办法,我们可以设置在缓冲区中一收到数据就同步给硬盘,但这很显然会导致读写硬盘次数增加,性能降低。但鱼和熊掌不可兼得。得到性能就会丢失数据可靠性,反之亦然。

AOF 缓冲区同步⽂件策略

        always 表示命令一进入缓冲区就同步到硬盘中,这是频率最高,数据可靠性最高,性能最低的方法。

        everysec 是默认配置,表示每秒同步一次缓冲区中的数据到硬盘中,这个策略兼顾了可靠性和安全性,理论上最多丢失 1 秒的数据。

        no 表示由操作系统来控制同步频率,但操作系统同步策略不可控,所以数据可靠性最低,一般不建议使用。

设置 AOF 缓冲区同步⽂件策略

在 redis.conf 配置文件(/etc)中可以设置 AOF 缓冲区同步⽂件策略:

重写机制

        随着命令不断写⼊ AOF,⽂件会越来越⼤,为了解决这个问题,Redis 引⼊ AOF 重写机制压缩⽂件体积。AOF ⽂件重写是把 Redis 进程内的数据转化为写命令同步到新的 AOF ⽂件。

重写后的 AOF 为什么可以变⼩?

有如下原因:

• 进程内已超时的数据不再写入⽂件。

• 旧的 AOF 中的⽆效命令,例如 del、hdel、srem 等重写后将会删除,只需要保留数据的最终版 本。

• 多条写操作合并为⼀条,例如 lpush list a、lpush list b、lpush list c从可以合并为 lpush list a b c。较⼩的 AOF ⽂件⼀⽅⾯降低了硬盘空间占⽤,⼀⽅⾯可以提升启动 Redis 时数据恢复的速度。

AOF 重写过程可以⼿动触发和⾃动触发

• ⼿动触发:调⽤ bgrewriteaof 命令。

• ⾃动触发:根据 auto-aof-rewrite-min-sizeauto-aof-rewrite-percentage 参数确定⾃动触发时机。

◦ auto-aof-rewrite-min-size:表⽰触发重写时 AOF 的最⼩⽂件⼤⼩,默认为 64MB。

◦ auto-aof-rewrite-percentage:代表当前 AOF 占⽤⼤⼩相⽐较上次重写时增加的⽐例。

AOF 重写的流程

1. 执⾏ AOF 重写请求。

        如果当前进程正在执⾏ AOF 重写,请求不执⾏。如果当前进程正在执⾏ bgsave(RDB 定期备份) 操作,重写命令延迟到 bgsave 完成之后再执⾏。

2. ⽗进程执⾏ fork 创建⼦进程。由子进程来完成重写操作,父进程继续对客户端提供服务

3. 重写

        a. 主进程 fork 之后(复制出子进程后),继续响应其他命令。所有修改操作写⼊ AOF 缓冲区并根据 appendfsync 策略同步到硬盘,保证旧 AOF ⽂件机制正确。

        b. ⼦进程只有 fork 之前的所有内存信息,⽗进程中需要将 fork 之后这段时间的修改操作写⼊AOF 重写缓冲区中。

4. ⼦进程根据内存快照,将命令合并到新的 AOF ⽂件中。

5. ⼦进程完成重写

        a. 新⽂件写⼊后,⼦进程发送信号给⽗进程。

        b. ⽗进程把 AOF 重写缓冲区内临时保存的命令追加到新 AOF ⽂件中。

        c. ⽤新 AOF ⽂件替换⽼ AOF ⽂件。

为什么子进程在重写时,还要把数据保存到旧 AOF 文件

        当子进程在根据内存中的数据重写 AOF 文件时,父进程响应的命令是子进程没有的,所以将这部分命令保存到缓冲区中,后续再将其保存到新 AOF 文件中,新 AOF 文件会替代旧 AOF 文件

        既然旧 AOF 文件会被替换,那为什么还要将保存到缓冲区的数据保存到旧 AOF 文件呢?为了避免极端情况,若子进程在重写的时候,Redis 服务器突然崩掉就会导致保存到缓冲区中的数据丢失,如果数据也保存到了旧 AOF 文件中,就没有什么大碍了。

AOF 收集了子进程重写期间主进程处理的命令,但 RDB 没有管

        相信有细心的小伙伴发现了,重写 AOF 文件时,专门用了一个缓冲区来保存子进程重写期间主进程所处理的命令,来保证所有的命令都被保存到 AOF 文件中,但 RDB 并没有理会子进程重写期间主进程处理的命令,它将这段时间的改变全部抛弃了。

        这是为什么?因为 RDB 是定期备份,这就代表它无法与最新的数据保持同步,而 AOF 是实时备份,它需要保证 AOF 文件中的内容与最新的数据保持同步。没有好坏之分,还是得看我们的业务需求

混合持久化

        AOF 文件中是字符数据,而 RDB 文件中是二进制数据,这就导致 Redis 读取 RDB 文件恢复数据的速度较快,那么我们不如让 AOF 重写的时候按照二进制来组织数据,因为重写也是按照 Redis 内存中的数据重写的,并不在乎过程。

        事实上 Redis 的开发人员们也确实这样做了,Reids 采用了混合持久化的方式,结合了 AOF 和 RDB 的优点。

        按照 AOF 的方式,将每一个操作都通过文本的方式记录到文件,在 AOF 文件重写时,就按照 RDB 的二进程方式将内存中的数据保存到新的 AOF 文件中,后续再进行的操作,依然是将命令通过文本形式追加在文件后面。

当 AOF 和 RDB 文件同时存在,用谁还原数据

        肯定是用 AOF ,因为 AOF 是实时备份,数据比 RDB 文件的定期备份更全。

        

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

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

相关文章

大数据智慧消防解决方案(24页PPT)

方案介绍: 大数据智慧消防解决方案是提升消防安全管理水平、保障人民群众生命财产安全的重要手段。通过集成物联网、云计算、大数据、人工智能等先进技术,构建集监测、预警、指挥、救援于一体的智慧消防系统,将为消防安全事业注入新的活力。…

单日收益1000+看了就会的项目,最新灵异短视频项目,简单好上手可放大操作

各位好友,佳哥在此与大伙儿聊聊一项神秘莫测的短视频项目。你或许会想,“又是一个视频创作项目?” 但别急,这个项目与众不同,日入千元不再是梦,而且它的易用性让人惊喜,无论你是初学者还是资深玩…

数据结构·一篇搞定队列!

hello,大家好啊,肖恩又拖更了,你们听我狡辩,前段时间有期中考试,so我就没什么时间写这个,在这给大家道个歉😭😭😭 我后面一定尽力不拖更 那么接下来,我们来看…

数字化转型必备:营销策划流程图,打造你的数字市场地图

制作营销策划流程图是一个系统化的过程,它可以帮助你清晰地规划和展示营销活动的各个阶段。 以下是制作营销策划流程图的步骤: 1.确定营销目标: 明确你的营销活动旨在实现的具体目标,比如提升品牌知名度、增加销售额、吸引新客…

【CCIE | 网络模拟器】部署 EVE-NG

目录 1. 环境准备2. 下载 EVE-NG 镜像3. 安装 EVE-NG 虚拟机3.1 创建 eve-ng 虚拟机3.2 选择存储3.3 定义虚拟机计算资源(1)开启CPU虚拟化功能(2)精简置备磁盘 3.4 检查虚拟机设置 4. 安装系统4.1 选择系统语言4.2 选择系统键盘类…

2024.05.25 第 131 场双周赛

Leetcode 第 131 场双周赛 求出出现两次数字的 XOR 值 [Leetcode 求出出现两次数字的 XOR 值](https://leetcode.cn/problems/find-the-xor-of-numbers-which-appear-twice/description/] 给你一个数组 nums ,数组中的数字 要么 出现一次,要么 出现两次…

自从有了可观测性,传统运维如何进行提升?

在 201x 年,随着容器技术的出现,容器的部署方式逐渐被各大互联网公司采用,相比物理机/虚拟机,容器的好处是环境隔离、轻量、快速。 但是管理容器是一件复杂的事情,后来出现了 Kubernetes,成为了事实上的容…

数据结构(五)树与二叉树

2024年5月26日一稿(王道P142) 基本概念 术语 性质 二叉树 5.2.2 二叉树存储结构

MySQL|主从复制配置

我使用的是两个云服务器,如果读者使用的是虚拟机和本机,配置会简单很多。 关于云服务器安全组设置、防火墙端口等问题请参考文章: 使用华为云服务器进行项目部署(云服务器、防火墙配置) 条件:master 和 s…

网络安全之安全协议浅谈

安全协议 安全协议概述安全协议分类IPSecIPSec安全协议IPSec架构IPSec封装模式AH协议ESP协议SET协议SET协议电子交易模型SET协议安全目标认证中心CA 安全协议概述 安全协议是信息交换安全的核心,它在网络不同层次上、针对不同应用,通过对各种密码学技术…

006、API_单线程

Redis使用了单线程架构和I/O多路复用模型来实现高性能的内存数据库 服务,本节首先通过多个客户端命令调用的例子说明Redis单线程命令处理 机制,接着分析Redis单线程模型为什么性能如此之高,最终给出为什么理 解单线程模型是使用和运维Redis的…

面向对象------多态

1.多态的定义 通俗来说,当同一种行为或者事情发生在不同的对象上,这些行为或者事情最终得到的结果不同。 注意:多态要发生在继承的基础上。 例如:彩色打印机和黑白打印机。 彩色打印机和黑白打印机是不同的对象,但…

微信小程序源码-基于Java后端的小区租拼车管理信息系统毕业设计(附源码+演示录像+LW)

大家好!我是程序员一帆,感谢您阅读本文,欢迎一键三连哦。 💞当前专栏:微信小程序毕业设计 精彩专栏推荐👇🏻👇🏻👇🏻 🎀 Python毕业设…

跟TED演讲学英文:How to escape education‘s death valley by Sir Ken Robinson

How to escape education’s death valley Link: https://www.ted.com/talks/sir_ken_robinson_how_to_escape_education_s_death_valley Speaker: Sir Ken Robinson Date: April 2013 文章目录 How to escape educations death valleyIntroductionVocabularySummaryTranscri…

使用残差网络识别手写数字及MNIST 数据集介绍

MNIST 数据集已经是一个几乎每个初学者都会接触的数据集, 很多实验、很多模型都会以MNIST 数据集作为训练对象, 不过有些人可能对它还不是很了解, 那么今天我们一起来学习一下MNIST 数据集。 1.MNIST 介绍 MNIST 数据集来自美国国家标准与技术研究所, National Institute of S…

Spring MVC+mybatis项目入门:旅游网(四)用户注册——mybatis的配置与使用以及Spring MVC重定向

个人博客:Spring MVCmybatis项目入门:旅游网(四)用户注册2-持久化 | iwtss blog 先看这个! 这是18年的文章,回收站里恢复的,现阶段看基本是没有参考意义的,技术老旧脱离时代(2024年…

MiniMax 悄咪咪上线的这款 AI 产品,好用到爆炸!

大模型太卷了!上周国外某款多模态大模型的出现,立刻掀起了 AI 领域对话式多模态交互的热潮。不管是文字、语音,还是图片,都能与你进行实时交互。随后,谷歌也推出了类似的 Astra。 然而,国外的交互式大模型…

线性回归模型之套索回归

概述 本案例是基于之前的岭回归的案例的。之前案例的完整代码如下: import numpy as np import matplotlib.pyplot as plt from sklearn.linear_model import Ridge, LinearRegression from sklearn.datasets import make_regression from sklearn.model_selectio…

2024年弘连网络FIC大会竞赛题线下决赛题

总结: FIC决赛的时候,很多小问题没发现,在pve平台做题确实很方便。 这套题目复盘完,服务器这块的知识确实收获了很多,对pve集群平台和网络拓扑也有了一定的认识,感谢各位大佬悉心指导。 接下来&#xff0…

【数据结构】哈希表的原理及其实现

文章目录 哈希表的概念哈希函数的设计常见的哈希函数 哈希冲突1. 闭散列代码实现 2. 开散列拉链法的优点 针对开散列哈希的扩展基于开散列拉链法封装哈希表MyHash.h 基于哈希表实现unordered_map类Myunordered_map.h 基于哈希表实现unordered_set类Myunordered_map.h 哈希表的概…