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 文件的定期备份更全。

        

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

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

相关文章

docker 安装RabbitMQ-web版本

直接拉去web版本 docker pull rabbitmq:management启动命令 设置用户名 admin 密码123456 docker run -dit --name rabbitmq -p 5672:5672 -p 15672:15672 -e RABBITMQ_DEFAULT_USERadmin -e RABBITMQ_DEFAULT_PASS123456 rabbitmq:management访问地址 http://127.0.0.1:…

GeoScene产品学习视频收集

1、易智瑞运营的极思课堂https://www.geosceneonline.cn/learn/library 2、历年易智瑞技术公开课视频资料 链接:技术公开课-易智瑞信息技术有限公司,GIS/地理信息系统,空间分析-制图-位置智能-地图 3、一些关于GeoScene系列产品和技术操作的视…

二进制部署k8s集群 部署高可用master节点

目录 本次部署的环境 一、master02 节点部署 二、负载均衡部署 安装nginx服务 部署keepalive服务 修改node节点上的配置文件 在master节点上创建pod 三、部署 Dashboard 二进制部署k8s集群部署的步骤总结 (1)k8s的数据存储中中心的搭建 etcd &…

Apache Log4j Server 反序列化命令执行漏洞(CVE-2017-5645)

漏洞复现环境搭建请参考 http://t.csdnimg.cn/MxmId 漏洞版本 Apache Log4j 2.8.2之前的2.x版本 漏洞验证 (1)开放端口4712 漏洞利用 (1)ysoserial工具获取 wget https://github.com/frohoff/ysoserial/releases/download/v0…

Flink DataStream API 基础算子(一)

一、介绍 官网 DataStream API 得名于特殊的 DataStream 类,该类用于表示 Flink 程序中的数据集合。你可以认为 它们是可以包含重复项的不可变数据集合。这些数据可以是有界(有限)的,也可以是无界(无限)的…

spring启动后自动退出了

在项目中启动spring框架的application,但是还未等到接口访问它就自己退出了,运行截图如下所示: 解决办法: 将build.gradle文件里的依赖修改一下。我原先的依赖是: org.springframework:spring-web:5.3.10 现修改为 …

2024 电工杯高校数学建模竞赛(B题)| 平衡膳食食谱 |建模秘籍文章代码思路大全

铛铛!小秘籍来咯! 小秘籍团队独辟蹊径,运用负载均衡,多目标规划等强大工具,构建了这一题的详细解答哦! 为大家量身打造创新解决方案。小秘籍团队,始终引领着建模问题求解的风潮。 抓紧小秘籍&am…

肯尼亚大坝决堤反思:强化大坝安全监测的必要性

一、背景介绍 近日,肯尼亚发生了一起严重的大坝决堤事件。当地时间4月29日,肯尼亚内罗毕以北的一座大坝决堤,冲毁房屋和车辆。当地官员称,事故遇难人数已升至71人。这起事件再次提醒我们,大坝安全无小事,监…

正点原子[第二期]Linux之ARM(MX6U)裸机篇学习笔记-23.1,2 讲 I2C驱动

前言: 本文是根据哔哩哔哩网站上“正点原子[第二期]Linux之ARM(MX6U)裸机篇”视频的学习笔记,在这里会记录下正点原子 I.MX6ULL 开发板的配套视频教程所作的实验和学习笔记内容。本文大量引用了正点原子教学视频和链接中的内容。…

了解区块链基础设施,共同构建安全且强大的Sui网络

区块链基础设施的范畴很广,但其核心是那些直接与网络互动的计算机。这些实体通常被称为节点,分为不同的类型,例如维护完整区块链副本的全节点,以及作为共识决定者的验证节点。除了这两种类型之外,还有其他类型的节点&a…

【oracle的安装记录】

oracle安装记录 一、下载以后,解压到同一路径下面 二、双击可执行安装文件,等待文件加载 三、双击以后,弹出信息 四、提示该窗口,点击【是】即可 五、未填写配置安全更新信息 六、弹出小窗口,选择【是】 七、安装选项…

SQLI-labs-第二十四关

目录 1、登录界面 2、注册界面 3、修改密码界面 知识点:二次注入 思路: 这一关有几个页面可以给我们输入,一个登录界面,一个注册页面,一个修改密码界面 1、登录界面 首先我们登录界面看看 登录后出现一个修改密码…

Ubuntu 搭建SRT协议 环境

1.官网clone源码 GitHub - Haivision/srt: Secure, Reliable, Transport 打不开的话国内gitee 不是最新的 https://gitee.com/smartavs/srt.git 下下来之后 cd 到srt目录 需要安装cmake openssl等依赖 我的环境已经有了 mkdir build && cd build cmake .. -…

最有效的企业数据防泄漏手段 | 数据泄漏防护系统推荐

随意信息安全意识不断提高,企业纷纷寻求高效的数据防泄漏手段。在众多解决方案中,这五款软件各具特色,但它们的共同目标都是确保企业数据的安全性和保密性。 接下来,我们将逐一介绍这五款软件的特点和优势。 1、Ping 32 Ping32…

前端项目使用docker编译发版和gitlab-cicd发版方式

项目目录 app/ ├── container/ │ ├── init.sh │ ├── nginx.conf.template ├── src/ ├── .gitlab-ci.yml └── deploy.sh └── Dockerfile └── Makefilecontainer目录是放nginx的配置文件,给nginx镜像使用 .gitlab-ci.yml和Makefile是c…

阿里云 EMR Serverless Spark 版开启免费公测

阿里云 EMR Serverless Spark 版是一款云原生,专为大规模数据处理和分析而设计的全托管 Serverless 产品。它为企业提供了一站式的数据平台服务,包括任务开发、调试、调度和运维等,极大地简化了数据处理的全生命周期工作流程。使用 EMR Serve…

LayUI使用(一)点击树组件的右边空白区域也可响应事件

前提: 如下,希望能够点击右边的空白区域也能够响应,而不仅仅是点击文本才响应 分析流程 一开始问了chatgpt,但它给的方案太麻烦了,而且还有错误,因此自己上手F12进入调试模式,点击查看最终渲…

文件外发审核是数据防泄漏的重要手段,那该怎么落地?

企业在日常经营中,无可避免地会产生文件外发的需求,文件发送对象包括但不限于合作方、供应商、客户、公关媒体、慈善组织等等,不一而足。而由于外发的对象不同,所涉及的文件类型也多种多样: 商业合作合同:…

STM32开发学习——使用 Cortex-M3M4M7 故障异常原因与定位(三)

STM32开发学习——使用 Cortex-M3M4M7 故障异常原因与定位(三) 文章目录 STM32开发学习——使用 Cortex-M3M4M7 故障异常原因与定位(三)文档说明:官方参考文档线上链接(可在线阅读与下载)&#…

【Python脚本随手笔记】-- 将 “庆余年2” 等信息写入 Txt 文件中

💌 所属专栏:【Python脚本随手笔记】 😀 作  者:我是夜阑的狗🐶 🚀 个人简介:一个正在努力学技术的CV工程师,专注基础和实战分享 ,欢迎咨询! &#…