一文带你搞懂Redis持久化

Redis持久化

Redis的数据是存储在内存的,当程序崩溃或者服务器宕机,那么内存里的数据就会丢失。所以避免数据丢失的情况,需要将数据保存到其他的存储设备中。

Redis提供两种方式来持久化,分别是

  • RDB(Redis Database):记录某个时刻的全部数据,本质是存储二进制数据的快照到磁盘,后续通过加载RDB文件恢复数据

  • AOF(Append Only File):记录执行的每条命令,通过重新执行命令来恢复数据。本质是记录操作日志,后续通过日志恢复数据。

RDB

本质

记录某个时刻的全部数据,本质是:将某一时刻Redis服务器内存中的数据保存到磁盘中的二进制文件中(dump.rdb),后续通过加载RDB文件恢复数据。

RDB触发(执行持久化)

RDB的触发包括手动触发,自动触发,关闭时持久化

  1. 手动触发包括主动执行sava命令,主动执行bgsave命令:

  • save命令:会在redis主线程执行持久化操作,会阻塞主线程,只有RDB持久化完成,才能响应客户端的请求,所以在生产模式的时候慎用(不用)。Redis在正常关闭时,会执行save命令来持久化数据

  • bgsave命令:background save,即后台保存。Redis会创建一个子进程来生成快照文件,创建子进程可能会有短暂的阻塞,而父进程(Redis的服务器进程)会继续处理客户端的请求。一般用的是这个命令

  1. 自动触发:

用户可以在Redis的配置文件中进行设置(默认开启),Redis会根据设置自动调用bgsave。比如,

#save <seconds> <changes>
save 900 1 表示每900秒内,有1条写数据操作,则触发bgsave
save 300 10 多条命令是并集关系,如果满足其中一个就会触发
RDB执行流程

Redis官网描述:

How it works
Whenever Redis needs to dump the dataset to disk, this is what happens:
1.Redis forks. We now have a child and a parent process.
2.The child starts to write the dataset to a temporary RDB file.
3.When the child is done writing the new RDB file, it replaces the old one.
This method allows Redis to benefit from copy-on-write semantics.
  1. Redis fork出一个子进程

  2. 子进程把数据写入临时的RDB文件

  3. 写完之,新RDB文件替换旧RDB文件

最后还有一句话:这种方式让Redis从”写时复制“技术收益。也就是,Redis在执行持久化的时候,依然可以处理客户端的命令,数据是可以被修改的。

具体来讲,fork创建子进程后,子进程会复制父进程的页表,页表指向的物理地址是同一个,所以子进程和父进程时共享同一片数据的。当父进程处理客户端请求,发生内存数据修改时,物理内存才会被复制一份给子进程,所以子进程的持久化操作是不会被影响。

AOF

记录执行的每条命令,通过执行命令来恢复数据。本质是记录操作日志,后续通过日志恢复数据。

AOF日志文件其实就是普通的文本,可以通过cat命令查看里面的内容。

Redis先执行写操作命令后,再将该命令记录到AOF日志中。有以下几点好处:

  1. 避免额外的检查开销。如果命令的语法有问题又不进行检查,直接先记录到AOF日志里,等到Redis使用日志文件恢复数据的时候,就会出错。所以先执行命令后,只有命令执行成功才记录到AOF日志中,就能避免额外的检查开销,保证AOF日志里的命令是正确的。

  2. 不会阻塞当前操作命令的执行。

当然也存在一定风险:

  1. 执行写操作和记录AOF日志是两个过程,当Redis还没有来得及将命令写入硬盘时,服务器宕机,数据就有丢失的风险

  2. 会阻塞下一个操作命令的执行。

因为执行命令和记录AOF日志都是在主进程完成的

开启AOF

打开redis配置文件

appendonly no
​
# The name of the append only file (default: "appendonly.aof")
​
appendfilename "appendonly.aof"

默认AOF是关闭的,通过设置appendonly为yes可开启

AOF写入流程
  1. 将数据写入AOF缓冲区中,这个缓冲区叫aof_buf,是一个sds数据

  2. 将aof_buf的数据写入AOF文件,此时还没有写入硬盘,而是拷贝到内核缓冲区page cache中。一共有4个时机,会调用一个flushAppendOnlyFile的函数,这个函数会使用write函数来将数据写入操作系统缓冲区

    1. 处理完事件后,等待下一次事件之前,也就是beforeSleep中

    2. 周期函数serverCron中

    3. 服务器退出之前的准备工作时

    4. 通过配置指令关闭AOF功能时

    内核缓冲区page cache:是操作系统内核中用于缓存磁盘数据的一部分内存区域

    硬盘缓冲区:是硬盘或磁盘控制器中的硬件缓存

  3. 将内核缓冲区的数据写入磁盘。即调用系统的flush函数,刷盘其实还是在flushAppendOnlyFile函数中,但是不一定调用了flushApeendOnlyFile,flush就一定会被调用。这里支持了刷盘时机的配置。

    /* Perform the fsync if needed. */
    if (server.aof_fsync == AOF_FSYNC_ALWAYS) {/* redis_fsync is defined as fdatasync() for Linux in order to avoid* flushing metadata. */latencyStartMonitor(latency);redis_fsync(server.aof_fd); /* Let's try to get this data on the disk */latencyEndMonitor(latency);latencyAddSampleIfNeeded("aof-fsync-always",latency);server.aof_last_fsync = server.unixtime;
    } else if ((server.aof_fsync == AOF_FSYNC_EVERYSEC &&server.unixtime > server.aof_last_fsync)) {if (!sync_in_progress) aof_background_fsync(server.aof_fd);server.aof_last_fsync = server.unixtime;
    }

注意:

  1. 为什么先将数据写入aof缓冲中,而不直接同步到磁盘呢?

    因为实时写入磁盘会带来很高的磁盘IO,影响性能

AOF写入策略(AOF日志写入磁盘时机)

Redis提供了三种写入策略,决定了AOF日志什么时候写入磁盘,包括

  • appendfsync always:每次写操作命令执行完之后,同步将AOF日志数据写入磁盘。

  • appendfsync everysec:每次写操作命令执行完之后,先将命令写入到AOF文件的内核缓冲区,然后每隔一秒将缓冲区里的内容写入磁盘

  • appendfsync no:Redis不去控制写入硬盘的时机,由操作系统控制。每次先将命令写入AOF文件的内核缓冲区,再由操作系统决定何时写入硬盘。一般情况linux会每30秒刷一次盘。这种策略对性能的影响最小,但发生崩溃时会丢失较多数据。

Redis的默认设置是每秒钟同步一次数据到磁盘,提供较好的性能和数据可靠性。也需要根据实际业务来选择,比如只是简单的缓存,不存在热点缓存,就可以30秒同步一次数据到磁盘中。Always策略每次执行写操作就同步将AOF日志写入硬盘,影响主进程的性能。

根据业务场景进行选择:

  • 如果要高性能,就选No策略

  • 如果要高可靠,就选Always策略

  • 如果折中,较好的性能和可靠性,就选Everysec策略

AOF重写

随着命令越来越多,AOF文件会越来越大,不仅占用大量磁盘空间,而且恢复数据也会变慢。

在AOF文件中,有些命令是没有作用的,比如一开始set一个数据为10,后来又set为100,那么前面set为10就没有作用了,完全可以把前面set为10的命令去掉。

所以,AOF重写机制的妙处在于,尽管某个键值对被多条命令重复修改,最终也只需用一条命令去记录这个键值对当前的最新状态,进而减少AOF日志中的命令数量。

AOF重写流程

写入AOF日志的操作是在主进程完成的,因为它写入的内容不多,所以不太影响命令的操作。

而AOF重写时,需要读取所有缓存的键值对数据,为每一个键值对生成一条命令,然后写入到新的AOF文件,重写完后,将旧AOF文件替换掉。所以AOF过程由后台子进程来完成,避免阻塞主进程。

这里使用子进程而不是线程,因为如果是使用线程,多线程之间会共享内存,那么在修改共享内存数据的时候,需要通过加锁来保证数据的安全,而这样就会降低性能。而使用子进程,创建子进程时,父子进程是共享内存数据的,不过这个共享的内存只能以只读的方式,而当父子进程任意一方修改了该共享内存,就会发生「写时复制」,于是父子进程就有了独立的数据副本,就不用加锁来保证数据安全。

  1. 重写时,主进程会fork出一个子进程,由子进程将这些Redis数据写入重写日志

  2. 在子进程进行重写期间,主进程也会将新的写操作写入到AOF重写缓冲区中

  3. 当新的AOF文件创建完毕,Redis就会将重写缓冲区的内容追加到新的AOF文件,新AOF文件替换旧AOF文件

所以,尽管重写过程中有新数据写入,通过追加AOF重写缓冲的方式到新文件,依然可以保证不会丢失最新的写入操作

AOF混合持久化

是什么

混合持久化发生在原有的AOF流程。开启了混合持久化,在AOF重写日志的时候,fork出来的子进程会将内存数据以RDB的方式写入新的AOF文件中,期间主进程将写操作命令写入重写缓冲区中,最后追加到新的AOF文件中。

此时的AOF文件前半部分是RDB格式的全量数据,后半部分是AOF格式的增量数据。

优势

既有RDB文件小,加载快的优势,也有AOF持久化数据损失少的优势。但因为含有二进制数据,可读性会差一些。

服务启动时如何加载数据

混合持久文件里有REDIS这个标记,加载时能通过这个标记进行判断是否开启了混合持久化。

可以通过配置文件开启,5.0之后默认是打开的,所以5.0之后只要AOF配置开启,默认就是混合持久化。

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

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

相关文章

字符串函数(二)—— 长度受限制的字符串函数

✨博客主页&#xff1a;小钱编程成长记 &#x1f388;博客专栏&#xff1a;进阶C语言 &#x1f388;相关博文&#xff1a;字符串函数&#xff08;一&#xff09; 字符串函数&#xff08;二&#xff09;—— 长度受限制的字符串函数 3.长度受限制的字符串函数3.1 strncpy&#x…

Redis配置和优化

Redis配置和优化 一 、Redis介绍二、关系数据库和非关系数据库2.1、关系型数据库2.2、 非关系型数据库2.3、 非关系型数据库的产生背景2.4、 关系型数据库和非关系型数据库区别2.5、 总结 三、缓存概念3.1、系统缓存3.2、 缓存保存位置及分层结构3.2.1、DNS缓存3.2.2、 应用层缓…

MySql进阶篇---006:存储引擎,索引,SQL优化,视图、存储过程、变量、流程控制、游标、存储函数、触发器

1. 存储引擎 1.1 MySQL体系结构 1).连接层 最上层是一些客户端和链接服务&#xff0c;包含本地sock 通信和大多数基于客户端/服务端工具实现的类似于TCP/IP的通信。主要完成一些类似于连接处理、授权认证、及相关的安全方案。在该层上引入了线程池的概念&#xff0c;为通过认证…

Java大数 -- BigInteger类

在java语言中&#xff0c;每一种整数类型都有自己的上限和下限&#xff0c;如果要想对非常大的整数做运算&#xff0c;就需要使用BigInteger类。特别在做算法题传入一个数值型的字符串时。 1.包 import java.math.*; 2.构造方法 public BigInteger(String str){...} BigInte…

10.1select并发服务器以及客户端

服务器&#xff1a; #include<myhead.h>//do-while只是为了不让花括号单独存在&#xff0c;并不循环 #define ERR_MSG(msg) do{\fprintf(stderr,"%d:",__LINE__);\perror(msg);\ }while(0);#define PORT 8888//端口号1024-49151 #define IP "192.168.2.5…

三等分功分器[波导]设计详细教程

想必大家通过阅读相关文献可以发现三等分实现可以有很多不同的方法&#xff0c;这里采用的是先不等分再等分的方式&#xff0c;仅供参考。 主要指标 中心频率为280GHz&#xff0c;采用WR-3频段的标准波导&#xff0c;将2:1不等功率分配耦合器与3dB等功率分配耦合器级联&#…

动态规划:两个数组的dp问题(C++)

动态规划&#xff1a;两个数组的dp问题 前言两个数组的dp问题1.最长公共子序列&#xff08;中等&#xff09;2.不同的子序列&#xff08;困难&#xff09;3.通配符匹配&#xff08;困难&#xff09;4.正则表达式&#xff08;困难&#xff09;5.交错字符串&#xff08;中等&…

【NLP的python库(03/4) 】: 全面概述

一、说明 Python 对自然语言处理库有丰富的支持。从文本处理、标记化文本并确定其引理开始&#xff0c;到句法分析、解析文本并分配句法角色&#xff0c;再到语义处理&#xff0c;例如识别命名实体、情感分析和文档分类&#xff0c;一切都由至少一个库提供。那么&#xff0c;你…

加入PreAuthorize注解鉴权之后NullPointerException报错

记录一次很坑的bug&#xff0c;加入PreAuthorize注解鉴权之后NullPointerException报错&#xff0c;按理来说没有权限应该403报错&#xff0c;但是这个是500报错&#xff0c;原因是因为controller层的service注入失败&#xff0c;然而我去掉注解后service注入成功&#xff0c;并…

初级篇—第三章多表查询

文章目录 为什么需要多表查询一个案例引发的多表连接初代查询笛卡尔积&#xff08;或交叉连接&#xff09;的理解 多表查询分类等值连接 vs 非等值连接自连接 vs 非自连接内连接VS外连接 SQL99语法实现多表查询内连接的实现外连接的实现左外连接右外连接满外连接 UNION的使用7种…

Mysql高手养成——第一章:索引知识,浅尝性能分析

&#x1f4e3; &#x1f4e3; &#x1f4e3; &#x1f4e2;&#x1f4e2;&#x1f4e2; 我是小冷 侧重后端的全栈工程师&#xff0c;有关技术问题需要讨论交流的直接私信即可 ⏩当前专栏&#xff1a;mysql高手养成系列- 第一章 索引与浅尝性能分析 ✏️高质量技术专栏专栏链接:…

解决前端二进制流下载的文件(例如:excel)打不开的问题

1. 现在后端请求数据后&#xff0c;返回了一个二进制的数据&#xff0c;我们要把它下载下来。 这是响应的数据&#xff1a; 2. 这是调用接口的地方&#xff1a; uploadOk(){if(this.files.length 0){return this.$Message.warning("请选择上传文件&#xff01;&#xff…

vite跨域proxy设置与开发、生产环境的接口配置,接口在生产环境下,还能使用proxy代理地址吗

文章目录 vite的proxy开发环境设置如果后端没有提供可以替换的/mis等可替换的后缀的处理办法接口如何区分.env.development开发和.env.production生产环境接口在生产环境下&#xff0c;还能使用proxy代理地址吗&#xff1f; vite的proxy开发环境设置 环境&#xff1a; vite 4…

Lua学习笔记:require非.lua拓展名的文件

前言 本篇在讲什么 Lua的require相关的内容 本篇需要什么 对Lua语法有简单认知 对C语法有简单认知 依赖Visual Studio工具 本篇的特色 具有全流程的图文教学 重实践&#xff0c;轻理论&#xff0c;快速上手 提供全流程的源码内容 ★提高阅读体验★ &#x1f449; ♠…

ChatGPT的截图识别功能测评:开启图像中的文字与信息的新纪元

文章目录 根据截图&#xff0c;识别菜品根据截图&#xff0c;识别数学公式根据截图生成前端UI代码可视化图像复现案例一案例二 更多可以使用的方向 制作人&#xff1a;川川 辛苦测评&#xff0c;如果对你有帮助支持一下书籍&#xff1a;https://item.jd.com/14049708.html 根据…

微信小程序,动态设置三级联动, 省市区街道

1.第一步 传parentId0 查询省份 2.第二步 选择省份,传pathId选择省份的pathId, 不传parentId,会查询出 市/县数据 3.第三步 根据选择县的parentId 查询街道数据,传parentId选择的县id 4.选择结果回显 显示所选择的 path 以/分割 取最后一级<van-dropdown-menu…

wustctf2020_name_your_cat

wustctf2020_name_your_cat Arch: i386-32-little RELRO: Partial RELRO Stack: Canary found NX: NX enabled PIE: No PIE (0x8048000)32位&#xff0c;开了NX和canary int shell() {return system("/bin/sh"); }有个后门函数 unsigned int…

【量化】量化原理浅析

前言 模型在端侧运行时&#xff0c;会追求模型保持原有精度的同时&#xff0c;让模型的运行速度更快。基本方向为模型压缩和加速&#xff0c;着力于减少网络参数量、降低计算复杂度。可通过以下方式实现&#xff1a; 针对网络结构本身进行改进&#xff0c;常用的3x3的卷积的叠加…

重置Jetson设备的Ubuntu密码:通过挂载根目录到另一个Linux系统

在本文中&#xff0c;我们将介绍如何在忘记Ubuntu 20.04密码的情况下重置密码。我们将通过将Ubuntu的根目录挂载到另一个Linux系统来实现这一目的。我们还将介绍chroot命令的功能。 1. 背景 最近&#xff0c;我们研发团队遇到了一个棘手的问题。一台用于研发&#xff0c;多人使…

大数据Doris(三):Doris编译部署篇

文章目录 Doris编译部署篇 一、Doris编译