深入Redis:细谈持久化

news/2024/9/19 0:41:18/ 标签: redis, 数据库

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.ppmy.cn/news/1519803.html

相关文章

Java Excel转PDF(免费)

目前市面上 Excel 转 PDF 的组件较多: 收费:aspose、GcExcel、spire开源:jacob、itextpdf 其中收费的组件封装得比较好,代码简洁,转换的效果也很好,但收费也高得离谱: 为了成本考虑&#xff…

videojs宫格视频选择播放

项目需要四宫格播放视频&#xff0c;而且还要实现点击视频加入播放。 首先&#xff0c;肯定要实现再一个页面上显示多个视频源并播放视频&#xff1a; <template><div><div v-for"(item,index) in videoList" :key"index" class"te…

在ElementUI项目中集成iconfont图标库

在前端项目开发中经常会遇到使用的组件库提供的ICON图标不够用的情况。最常见的解决方案无非就是把设计图的图标切图引入到项目中。还有就是使用svg图标&#xff0c;封装一个渲染组件在项目里面直接引入这个组件。 本文将介绍另一种方法&#xff0c;即集成iconfont图标库的图标…

9、LLaMA-Factory项目微调介绍

1、LLaMA Factory 介绍 LLaMA Factory是一个在GitHub上开源的项目&#xff0c;该项目给自身的定位是&#xff1a;提供一个易于使用的大语言模型&#xff08;LLM&#xff09;微调框架&#xff0c;支持LLaMA、Baichuan、Qwen、ChatGLM等架构的大模型。更细致的看&#xff0c;该项…

flutter 手写时钟

前言&#xff1a; 之前看过别人写的 js实现的 时钟表盘 挺有意思的&#xff0c;看着挺好 这边打算自己手动实现以下。顺便记录下实现过程&#xff1a;大致效果如下&#xff1a; 主要技术点&#xff1a; 表盘内样 倒角&#xff1a; 表盘下半部分是有一点倒角的感觉&#xff0c;…

尚品汇-MQ模块搭建测试、消息不丢失(重)(四十三)

目录&#xff1a; &#xff08;1&#xff09;消息不丢失 &#xff08;2&#xff09;消息确认 &#xff08;3&#xff09;消息确认业务封装 &#xff08;4&#xff09;封装发送端消息确认 &#xff08;5&#xff09;封装消息发送 &#xff08;6&#xff09;发送确认消息测试…

鸿蒙(API 12 Beta3版)【媒体资源使用指导】Media Library Kit媒体文件管理服务

应用可以通过photoAccessHelper的接口&#xff0c;对媒体资源&#xff08;图片、视频&#xff09;进行相关操作。 说明 在进行功能开发前&#xff0c;请开发者查阅[开发准备]&#xff0c;了解如何获取相册管理模块实例和如何申请相册管理模块功能开发相关权限。文档中使用到p…

基于深度学习的游客满意度分析与评论分析【情感分析、主题分析】

需要本项目的可以私信博主 目录 1 绪论 1.1 选题背景及研究意义 1.1.1 选题背景 1.1.2 研究意义 1.2 研究内容与方法 1.2.1 研究内容 1.2.2 研究方法 1.3 创新与不足 1.3.1创新点 1.3.2研究局限性 2 文献综述 2.1 相关概念界定 2.1.1 大数据分析 2.1.2 游客满意度 2.2 国内外研…

大数据系列之:查看Centos服务器用户可以创建的最大线程数、查看系统内核支持的最大线程数、查看系统支持的最大进程数、设置最大线程数限制、查看进程使用的线程数

大数据系列之:查看Centos服务器用户可以创建的最大线程数、查看系统内核支持的最大线程数、查看系统支持的最大进程数、设置最大线程数限制、查看进程使用的线程数 显示当前用户的资源限制查看用户可以创建的最大线程指定进程的资源限制查看系统内核支持的最大线程数查看系统支…

React 入门第八天:性能优化与开发者工具的使用

随着对React的逐步深入&#xff0c;我开始关注如何优化React应用的性能&#xff0c;特别是在复杂的组件树和频繁的状态更新中保持应用的高效性。这一天&#xff0c;我集中学习了React中的性能优化策略&#xff0c;并探索了如何使用React开发者工具来调试和优化应用。 1. 组件的…

续:当有数据时添加slave2

【示例】 另启一台虚拟机&#xff0c;作为mysql3. 新的虚拟机没有mysql软件包&#xff0c;如何才能快速部署&#xff1f;通过mysql1. mysql1&#xff1a; [rootmysql1 ~]# rsync -al /usr/local/mysql/ root172.25.254.166:/usr/local/mysql The authenticity of host 172.25…

Java算法之快速排序(Quick Sort)

快速排序&#xff1a;分而治之的高效排序算法 简介 快速排序是一种分而治之的排序算法&#xff0c;由C. A. R. Hoare在1960年提出。它通过选取一个元素作为"基准"&#xff08;pivot&#xff09;&#xff0c;然后重新排列数组&#xff0c;使得所有比基准值小的元素都…

【软考】【多媒体应用设计师】媒体与技术

1. 多媒体技术改变了传统循序式模式&#xff0c;用户可以借助超文本链接等方式&#xff0c;更自由灵活地访问所需的信息&#xff0c;体现了其&#xff08; &#xff09;的特点。 A.控制性 B.非线性 C.集成性 D.实时性 答案解析&#xff1a;本题考查信息多媒体非线性特点。多媒体…

安防监控/软硬一体/视频汇聚网关EasyCVR硬件启动崩溃是什么原因?

安防视频监控EasyCVR安防监控视频系统采用先进的网络传输技术&#xff0c;支持高清视频的接入和传输&#xff0c;能够满足大规模、高并发的远程监控需求。EasyCVR平台支持多种视频流的外部分发&#xff0c;如RTMP、RTSP、HTTP-FLV、WebSocket-FLV、HLS、WebRTC、WS-FMP4、HTTP-…

vue part 5

生命周期 <!DOCTYPE html> <html><head><meta charset"UTF-8" /><title>引出生命周期</title><!-- 引入Vue --><script type"text/javascript" src"https://cdn.jsdelivr.net/npm/vue/dist/vue.js&quo…

进程、线程的区别

进程&#xff08;Process&#xff09;和线程&#xff08;Thread&#xff09;是操作系统中的基本概念&#xff0c;它们在资源管理和任务执行方面有着本质的区别&#xff1a; 定义&#xff1a; 进程&#xff1a;进程是操作系统进行资源分配和调度的一个独立单位。每个进程都有自己…

ArcGIS Pro 3.1下载分享

在使用了很长一段时间ArcGIS Pro 3.0之后&#xff0c;终于迎来了ArcGIS Pro 3.1的更新&#xff0c;这里为你分享一下ArcGIS Pro 3.1的安装步骤。 软件介绍 ArcGIS Pro 3.1 是由Esri发布的地理信息系统 (GIS) 软件的较新版本&#xff0c;作为 ArcGIS 桌面应用程序家族中的核心…

【递归深搜之记忆化搜索算法】

1. 斐波那契数 解法一&#xff1a;递归 class Solution { public:int fib(int n) {return dfs(n);}int dfs(int n){if(n 0 || n 1)return n;return dfs(n - 1) dfs(n - 2);} }; 解法二&#xff1a;记忆化搜索 class Solution {int nums[31]; // 备忘录 public:int fib(int …

使用C++,仿照string类,实现myString

类由结构体演化而来&#xff0c;只需要将struct改成关键字class&#xff0c;就定义了一个类 C中类和结构体的区别&#xff1a;默认的权限不同&#xff0c;结构体中默认权限为public&#xff0c;类中默认权限为private 默认的继承方式不同&#xff0c;结构体的默认继承方式为p…

微型直线导轨高精度运行的工作原理

微型导轨是一种用于高精度定位和运动控制的传动装置&#xff0c;常用于微小化、高精密度化的机械设备中&#xff0c;如IC制造设备、半导体设备、高速移载的设备、精密测量、检测仪器、医疗设备、X-Y table&#xff0c;以及高速皮带驱动的设备等小型化设备。 微型导轨的构成相对…