深入Redis:细谈持久化

news2024/12/26 11:04:28

Redis的数据是保存在内存中的,内存里面的数据是不持久的,要想做到持久化,必须要把在内存中的数据储存到硬盘上。

Redis速度非常快,数据只有在内存中才有这样的速度,但是为了持久,数据还是要想办法保存到硬盘上去。于是,Redis决定,内存中也存数据,硬盘上也存数据,这样的两份数据理论上是完全一样的。

当需要插入一个新的数据的时候,就把这个数据同时写入到内存和硬盘,当查询某个数据的时候直接从内存里面读取,硬盘里面的数据只是在redis重启的时候,用来恢复内存里面的数据的。

具体来说,Redis有两种持久化的策略:RDB和AOF。

目录

RDB

手动触发

bgsave执行流程

dump.rdb

自动触发

AOF

同步频率

重写机制

重写流程

混合持久化


RDB

RDB,Redis DataBase ,也就是定期备份。

RDB定期的把我们Redis内存中的所有数据,都写入到硬盘中,生成一个快照。后续Redis一旦重启,就可以根据快照来把数据重新恢复到内存中。

“定期”,具体来说,有两种方式:手动触发和自动触发。

手动触发

通过redis客户端,执行特定的命令,来触发快照的生成。

这个特定的命令就是 save  或者  bgsave(backgroud)。

执行save的时候,redis会全力以赴的进行“快照生成”操作,此时会阻塞redis的其他客户端的命令。

但是并不推荐这样的方式,因为会占用大量的资源,会导致类似于 keys * 的后果。

所以我们主要讲解的是bgsave。

bgsave处理的时候,是不会影响到Redis服务器处理其他客户端的请求和命令。是如何做到的呢?Redis不是单线程的吗?此处Redis使用的就是“多线程”的方式来完成的并发编程。

bgsave执行流程

按照 1) 2) 3) 4) 5)的顺序来看,bgsave在后台异步地保存当前数据库的数据到磁盘。这个过程是通过创建一个子进程(fork)来完成的,这样可以避免在数据保存过程中阻塞主进程,从而影响Redis的性能。等到子进程完成生成RDB文件以后,在通过一个信号通知父进程。

dump.rdb

redis生成的rdb文件,是存放在redis的工作目录中的,可以在redis配置文件中设置。

redis.conf文件中,有一个名为dir的配置项,它指定了RDB文件和AOF文件的存储目录。

dir /var/lib/redis

后续redis服务器重新启动,就会尝试加载这个rdb文件。如果这个文件的格式或者某方面有错误,也可能导致数据加载失败。这里具体redis会怎么样,取决于rdb文件坏的地方在哪里,如果坏的地方正好是在文件末尾,就有可能还能正常启动,但是如果中间位置坏了,可能直接启动失败了。

当生成rdb镜像的时候,此时就会要把生成的快照数据,保存到一个临时文件中,当这个快照生成完毕之后,会先删除之前的rdb文件,再把新生成的rdb文件的名字改成刚才的dump.rdb。

自动触发

在Redis配置文件中,可以自己设置Redis每隔多久/修改多少次 就可以触发RDB。

  • save 900 1:如果在900秒(15分钟)内至少有1个键被修改,则保存数据库。
  • save 300 10:如果在300秒(5分钟)内至少有10个键被修改,则保存数据库。
  • save 60 10000:如果在60秒内至少有10000个键被修改,则保存数据库。

假设我们随便插入几个键值对,没有运行手动触发的命令,也达不到自动触发的条件。但是这一些数值都是可以修改的,但是需要注意的是:生成一次RDB快照,成本还是比较高的,不能让这个操作执行的太频繁。

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

  1. 12:00:00  生成了rdb
  2. 12:00:01  redis收到了大量的key变化请求
  3. 12:01:00  生成下一个快照文件

如果在第二步的过程中,redis服务器挂了,或者被异常重启(如kill - 9或者服务器掉电),就会导致12:00:00之后的数据都丢了。解决这个的办法就是AOF,我们之后再说。

如果使用service redis-server restart (shutdown命令),redis服务器也会触发生成快照这一操作。

RDB最大的问题,就是不能实时的持久化保存数据,在两次生成快照之间,实时数据可能会随着服务器重启而丢失。

AOF

AOF,append only file,会把用户的每个操作都记录到文件中,当redis重新启动的时候,就会读取这个aof文件中的内容,用来恢复数据。

AOF一般是关闭状态,通过修改配置文件可以打开。

那redis是一个单线程的服务器,在操作内存的同时,又要实时操作aof,同时写硬盘和内存,速度怎么保证?

实际上,AOF机制并不是直接让工作线程把数据写入硬盘,而是先写数据到内存中的缓冲区,等到有一定量之后再统一写入硬盘。

但是这不就是和RDB一样的问题了吗,如果数据在内存缓冲区里面,还没有写入到硬盘里面就主机掉电等出现异常,那岂不是还是会有部分数据丢失?

同步频率

其实这就是程序员需要做的取舍,redis给出了一些选项,刷新频率越高,性能影响就越大,同时数据的可靠性就越高;刷新频率越低,性能影响就越小,数据的可靠性就越低~

在配置文件中,有一个appendfsync选项可以自行设置。

重写机制

AOF文件持续增长,体积会越来越大,而且会影响到下一次 redis的启动时间。有没有什么办法能够减少AOF的体积呢?在AOF文件中,有一些内容是冗余的,比如:

对于AOF文件来说,我们可以忽略一些操作的过程,只关注操作的结果,这样就能够节省很多的资源占用。这就是Redis的重写机制,能够针对AOF文件进行整理操作,这个整理就能够剔除其中的冗余操作,并且合并一些操作,达到给AOF文件瘦身的效果。

重写流程

对于AOF的重写来说,仍然会创建子进程fork。父进程仍然负责接收请求,子进程负责对AOF文件进行重写。重写的时候,不关心AOF文件中原来都有一些什么,只关心内存中最终的数据状态。子进程只需要把内存中当前的数据获取出来,以AOF的格式写入到一个新的AOF文件中。

因为内存中的数据的状态,就已经相当于把AOF文件整理后的模样了。

  1. 在fork后,子进程写新的AOF文件,父进程仍然在不停的接受客户端的新请求,父进程会把这些请求产生的AOF文件先写到缓冲区里面,再刷新到原来的AOF文件。
  2. 在创建子进程的一瞬间,子进程就继承了当前父进程的内存状态,因此子进程的内存数据是父进程fork之前的状态,fork之后,新来的请求子进程是不知道的,它在自己干自己的事。
  3. 父进程又准备了一个aof_rewrite_buf缓冲区,专门放fork之后收到的数据。等待子进程写完新的AOF文件后,再把缓冲区里面的文件写入到新AOF文件中,就可以用新的AOF文件代替旧的AOF文件了。
  4. 父进程fork完之后,仍然在写旧的AOF文件,并且随着时间的推移新的AOF文件也会完成,那父进程还有必要在fork之后写旧的AOF文件吗?考虑极端情况,fork后子进程重写一半了,但是服务器挂了,子进程的数据就会丢失,新的AOF文件内容还不完整。如果父进程不写旧的AOF文件,重启就无法保证数据的完整性了。

如果在执行bgrewriteaof的时候,此时redis已经在进行AOF重写了,就不会再次执行AOF重写,会直接返回。

如果在执行bgrewriteaof的时候,发现当前redis在生成rdb文件的快照,此时AOF就会等待,等待RDB快照生成完毕再进行AOF重写。

其实AOF这样做的好处就是:RDB对于fork之后的数据就置之不理,而AOF则采用了aof_rewrite_buf来处理。这也就是RDB和AOF的设计理念不同,前者强调定期备份,而后者则是强调实时备份。

混合持久化

AOF本来是按照文本的方式来写入文件的,但是文本的方式写文件,后续加载的成本是比较高的,redis就引入了“混合持久化”的方式,结合了RDB和AOF的特点。

通过这个配置可以打开混合持久化,默认是打开的。

按照AOF的方式,每一个请求、操作都记录到文件里面,在触发了AOF重写操作后,就会把当前的内存按照rdb的二进制格式写入到新的AOF文件中,后续再进行的操作仍然是按照AOF文本的方式追加到文件后面。

当Redis上同时存在AOF文件和RDB快照的时候,以AOF为主,RDB就被忽略了~

至此,Redis持久化就告一段落了~之后还会继续进行Redis的学习~

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

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

相关文章

【分治——归并排序】排序数组的归并方法

目录 1.前言2.题目简介3.求解思路4.示例代码 1.前言 今天简单展示一个归并排序解题&#xff0c;难度简单。 2.题目简介 题目链接&#xff1a;LINK 3.求解思路 4.示例代码 //归并排序 class Solution { public:vector<int> tmp;vector<int> sortArray(vector&…

【Web开发工具】基于Windows系统下的WebStorm安装教程

目录 安装WebStorm1.官网下载WebStorm2.选择安装位置3.关闭应用 下载并解压工具下载地址解压执行Done输入Code 安装WebStorm 1.官网下载WebStorm 我自己的网盘链接: https://pan.baidu.com/s/17PJu8Kf_fdX3gi588ubTqQ?pwd6666 2.选择安装位置 下一步下一步就行&#xff0c…

有手就会之使用Dify构建RAG聊天应用(基于私有知识库和搜索引擎)

之前我的文章里写的是通过langchain来构建RAG应用&#xff0c;对于很多人来说。langchain作为一个框架上手难度大&#xff0c;代码不够直观。但是通过dify你将学会可视化搭建工作流。 什么是dify&#xff1f; Dify 是一款开源的大语言模型(LLM) 应用开发平台。它融合了后端即…

如何判断B端真实需求?5大经验技巧

准确判断B端真实需求能确保软件开发项目紧贴用户实际需求&#xff0c;减少返工&#xff0c;加快开发速度&#xff0c;提升客户满意度和产品竞争力。如果没有采用有效的技巧和经验来判断B端的真实需求&#xff0c;可能会导致软件开发项目偏离客户实际需求&#xff0c;引发频繁的…

【数据分析预备】Numpy入门

Jupyter Notebook 是一个基于网页的交互式计算环境编写代码、运行代码、查看输出、可视化数据、分享报告文档按单元格运行代码可展示的信息格式更丰富&#xff08;支持Markdown和Latex)交互式运行环境 安装 cmd窗口 pip install notebook启动 jupyter notebook退出 CtrlC …

阿里巴巴alibaba商品采集API获取商品列表商品详情接口

在跨境电商和B2B贸易日益繁荣的今天&#xff0c;如何高效、准确地获取商品信息成为了商家们关注的焦点。阿里巴巴作为全球领先的B2B电商平台&#xff0c;凭借其庞大的商品数据库和强大的技术支持&#xff0c;为商家们提供了丰富的API接口服务&#xff0c;其中alibaba.item_get接…

第十三节:学习Springboot整合mybatis——完整篇(自学Spring boot 3.x的第三天)

大家好&#xff0c;今天记录下学习springboot的第三天。​网创有方 这节详细记录了如何使用springboot整合mybatis方法&#xff0c;并成功实现将请求信息插入本地的mysql数据库。 由于只是为了方便本地验证&#xff0c;实际项目是需要部署到服务器上去的&#xff0c;所以就采用…

MQ专题:消费幂等性

一、提要 1.1 通过本文将获得 消息投递的通用代码 非事务消息的投递事务消息的投递任意延迟消息的投递&#xff0c;不依赖于任何MQ上面这些投递都支持批量的方式投递失败自动重试的代码 幂等消费的通用代码消费失败&#xff0c;衰减式自动重试的通用代码 1.2本文涉及到的主要…

新一代网络研发利器——开物™,让用户每一行代码都贡献在核心创新

随着云计算、人工智能、大数据的快速发展&#xff0c;现有的IT系统越来越复杂&#xff0c;传统网络技术难以满足新的业务需求&#xff0c;DPU技术开始崭露头角&#xff0c;越来越多的企业与研究机构认识到高性能网络处理技术带来的巨大价值&#xff0c;并积极开展创新与实践&am…

985硕闭着眼都有15k以上的月薪

985 闭眼 今天在牛客上看到一篇直呼好家伙的帖子&#xff1a; 这位同学指出&#xff1a;论坛里个个 985 的硕士闭着眼睛都有 15k 以上的月薪&#xff0c;还天天嚷嚷着研究生白读了&#xff0c;天天嚷嚷着反向读研了 ... 通常这样的帖子&#xff0c;都会被评论区喷成筛子。 结果…

微积分复习笔记 Calculus Volume 1 - 1.3Trigonometric Functions

1.3 Trigonometric Functions - Calculus Volume 1 | OpenStax

ELK日志服务收集SpringBoot日志案例

第一步&#xff1a;准备docker-compose文件 首先准备 docker-compose.yaml 文件 version: "3" services:elasticsearch:image: elasticsearch:7.17.2container_name: elasticsearch-servernetworks:- hostenvironment:- "cluster.nameelasticsearch" #设…

NeRF原理学习

一个2020年的工作我现在才来学习并总结它的原理&#xff0c;颇有种“时过境迁”的感觉。这篇总结是基于NeRF原文 NeRF: Representing Scenes as Neural Radiance Fields for View Synthesis 阅读理解后写的&#xff0c;作用是以后如果记不太清了可以回忆。 目的&应用 先说…

80.动态申请内存

目录 一.malloc函数 二.其他注意事项 三.视频教程 在定义变量的时候会在内存中申请空间。除了在定义变量的时候申请内存空间&#xff0c;也可以使用库函数动态申请内存&#xff0c; 一.malloc函数 作用&#xff1a;动态申请一块连续的任意尺寸的内存空间。 函数原型&…

【前端9】手风琴v1.0版本:使用插槽实现动态内容插入的Vue组件

【前端9】手风琴&#xff1a;使用插槽实现动态内容插入的Vue组件 写在最前面一、插槽的基本概念1.默认插槽2.具名插槽 二、实现一个折叠面板组件0.关键点和注意事项1.父组件 App.vue2.子组件 Collapse.vue总结 3.详细解读&#xff08;可以略过&#xff09;父组件子组件 三、小结…

通用后台管理系统实战演示(Vue3 + element-plus)汇总篇三

天行健&#xff0c;君子以自强不息&#xff1b;地势坤&#xff0c;君子以厚德载物。 每个人都有惰性&#xff0c;但不断学习是好好生活的根本&#xff0c;共勉&#xff01; 文章均为学习整理笔记&#xff0c;分享记录为主&#xff0c;如有错误请指正&#xff0c;共同学习进步。…

Python任务编排和工作流管理库之prefect使用详解

概要 在数据工程和科学的世界中,任务编排和工作流管理变得越来越重要。随着数据处理任务的复杂性增加,开发人员需要一种可靠且易于使用的工具来设计、监控和管理这些任务。Prefect 是一个用于构建、监控和管理数据管道的 Python 库,它简化了工作流的创建和执行,同时提供了…

028、架构_高可用_主从原理

MySQL半同步复制概览 MySQL主从复制是一个异步的复制过程,主库发送更新事件到从库,从库读取更新记录,并执行更新记录,使得从库的内容与主库保持一致。主从复制的基本过程如下图所示: 主从复制的完成通过以下三个进程实现的主库 binary log dump 线程:当从库连接主库时,…

22. K8S及DevOps

22. K8S及DevOps 一. 章节简介二. DevOps1. 简介2. CICD三. Kubernetes1. [官网](https://kubernetes.io/zh-cn/)--------------------------------------------------------------------------------------------------------一. 章节简介 二. DevOps 1. 简介 2. CICD

【科研新手必备】如何高效、高质量、科学的科研?

文献下载网站—英文写作小工具—SCI选刊 1、文献下载网站 中国知网 sci-hub 大木虫学术导航 学术资源搜索 2、英文写作小工具 DeepL 学术短语库 SCI写作辅导材料 赛特新思 3、SCI选刊 Journal Finder SPRINGER NATURE