当前位置: 首页 > news >正文

Redis:持久化

Redis:持久化

    • 持久化
    • RDB
      • dump.rdb
      • 优缺点
    • AOF
      • 文件同步
      • 重写机制
    • 混合持久化


持久化

虽然Redis是一个内存级别的数据库,但是Redis也是有持久化的能力的。当系统崩溃时,Redis就会被强制退出,此时内存中的数据就会丢失。为了能够在下次重启时恢复数据,Redis会把数据在硬盘中备份一份,也就是说Redis持久化的目的不是为了保存更多的数据,而是为了恢复数据。

Redis有两种处理持久化的方式,RDBAOF,两者的区别可以简单理解如下:

  • RDB:定期同步内存与硬盘的数据
  • AOF:只要内存的数据被修改,立刻同步到硬盘

本博客就基于这两种方式,讲解Redis的持久化。


RDB

RDB全称Redis DataBase,用于持久化Redis中的数据,其会定期把Redis的数据保存下来,这份数据就称为一个快照,随后存储到硬盘中。

除了等到指定时间,让其自动生成快照,RDB还支持程序员通过指令生成快照:

  • save:此时Redis会立刻生成快照,但是由于Redis是单线程模型,其它的所有操作都会被阻塞
  • bgsaveRedis立刻生成快照,但是是在后台运行,不会影响其他操作

在实际开发中,一般都使用bgsave,而不是save。此时就有疑问了,Redis不是单线程模型吗?如何做到在后台生成快照,而不影响其他操作的?

其实Redis在这使用了多进程的模式,流程如下:

在这里插入图片描述

当用户执行bgsave,此时父进程通过fork创建子进程,随后子进程去完成快照生成,父进程继续响应其他命令。当子进程持久化完毕,就给父进程发送信号通知父进程。如果父进程在收到信号之前,收到了来自其他用户的bgsave命令,此时不做处理直接返回,因为已经有子进程正在进行持久化了,此时多个bgsave命令只执行一次持久化。

此处的forkLinux的一个系统调用,因为Redis本身就只支持在Linux上运行,所以就直接用Linux的系统调用了。当执行fork时,会把父进程拷贝一份一模一样的出来,比如进程地址空间,页表,PCB等等,都会拷贝一份。当然也包括内存中的数据,此时子进程就可以拿到Redis原先的所有数据,进而生成快照

但是要是把变量全部拷贝一份,不会很浪费空间吗?其实这里用了一个写时拷贝,子进程和父进程刚拷贝完,其实是使用相同的内存数据,当父子进程任何一方进行了写入,才会发生拷贝。所以其实最后子进程几乎没有发生多少拷贝,又可以看到父进程的数据,进而生成快照。


dump.rdb

那么RDB文件到底在哪里?

打开Redis的配置文件,/etc/redis/redis.conf,可以找到以下内容:

# The working directory.
#
# The DB will be written inside this directory, with the filename specified
# above using the 'dbfilename' configuration directive.
#
# The Append Only File will also be created inside this directory.
#
# Note that you must specify a directory here, not a file name.
dir /var/lib/redis

dir后的路径,就是存储RDB文件的存储位置。在该目录下,会有一个dump.rdb文件,这就是生成的快照。这个文件内部存储的是二进制,如果直接查看会得到乱码。

并且这个数据不是简单的二进制存储,还会进行压缩,提高存储效率。

那么RDB的文件多久更新一次?这也在配置文件中:

# Save the DB to disk.
#
# save <seconds> <changes> [<seconds> <changes> ...]
#
# Redis will save the DB if the given number of seconds elapsed and it
# surpassed the given number of write operations against the DB.
#
# Snapshotting can be completely disabled with a single empty string argument
# as in following example:
#
# save ""
#
# Unless specified otherwise, by default Redis will save the DB:
#   * After 3600 seconds (an hour) if at least 1 change was performed
#   * After 300 seconds (5 minutes) if at least 100 changes were performed
#   * After 60 seconds if at least 10000 changes were performed
#
# You can set these explicitly by uncommenting the following line.save 3600 1 300 100 60 10000

找到Save the DB to disk.字段,这就是RDB的自动保存机制,配置文件的格式为:

save <seconds> <changes> [<seconds> <changes> ...]

只要在seconds秒内到达了changes次数的修改,那么就会更新文件,比如save 3600 1 300 100 60 10000的意思就是:

  1. 如果在3600 s内修改了1次数据,3600秒后更新dump.rdb
  2. 如果在300 s内修改了100次数据,300秒后更新dump.rdb
  3. 如果在60 s内修改了10000次数据,60秒后更新dump.rdb

另外的,如果配置save “”,也就是加一个空字符串,相当于禁止通过该方式自动更新。

除此之外,Redis还有一些其他方式也会自动生成快照: 0

  1. 通过配置文件的save属性,定期生成快照
  2. Redis正常关闭时
  3. 进行主从复制时
  4. 执行flushall指令时

优缺点

优点:

  • 因为RDB会把数据进行压缩,所以RDB的存储效率很高,占用的硬盘资源少
  • 通过RDB恢复,效率比AOF快很多

缺点:

  • 每次生成RDB都要额外创建一个子进程,这需要消耗额外的资源,执行

AOF

AOF全称Append Of File,其保存的是Redis的每一个具体操作,类似于MySQL的保存方式。AOF模式默认关闭,在配置文件中有以下内容:

############################## APPEND ONLY MODE ################################ By default Redis asynchronously dumps the dataset on disk. This mode is
# good enough in many applications, but an issue with the Redis process or
# a power outage may result into a few minutes of writes lost (depending on
# the configured save points).
#
# The Append Only File is an alternative persistence mode that provides
# much better durability. For instance using the default data fsync policy
# (see later in the config file) Redis can lose just one second of writes in a
# dramatic event like a server power outage, or a single write if something
# wrong with the Redis process itself happens, but the operating system is
# still running correctly.
#
# AOF and RDB persistence can be enabled at the same time without problems.
# If the AOF is enabled on startup Redis will load the AOF, that is the file
# with the better durability guarantees.
#
# Please check https://redis.io/topics/persistence for more information.appendonly no

只需要把appendonly后面的值改为yes就可以打开这个模式了,一旦这个模式打开,那么RDB模式就会失效。

修改配置文件后,要重启redis服务端:

service redis-server restart

在该字段的后面,紧跟着AOF的文件存储位置:

appendfilename "appendonly.aof"# For convenience, Redis stores all persistent append-only files in a dedicated
# directory. The name of the directory is determined by the appenddirname
# configuration parameter.appenddirname "appendonlydir"

在这里插入图片描述

打开.aof文件,可以看到以下格式的语句:

*2^M
$6^M
SELECT^M
$1^M
0^M
*8^M
$4^M
XADD^M
$58^M
pcp:values:series:2756fc65948d7070a2a980759d7e4267d49ccef4^M
$6^M
MAXLEN^M

可以看到很多认识指令,比如SELECTXADDMAXLEN

那么AOF模式下,每次操作都要把指令保存到硬盘,这种IO操作是非常低效的,那不是会极大的降低Redis的执行效率?

其实Redis这里采用了一个缓冲的策略,每次操作都把指令保存到aof_buf缓冲区中,这是一个内存区域,对内存的读写非常高效,当aof_buf内部的数据量达到一定值,才会写入硬盘。这样就减少了IO次数,保证了Redis的效率。


文件同步

aof_buf的数据写入到硬盘的文件,称为文件同步。文件同步有多种策略,如果同步的频率高了,那么Redis的效率就会低,但是如果同步的频率太低了,由于缓冲区在内存中,一旦程序崩溃,丢失的数据就更多。因此Redis给用户提供了多个级别,让用户自己取舍。

在配置文件中,可以设置同步频率:

# The fsync() call tells the Operating System to actually write data on disk
# instead of waiting for more data in the output buffer. Some OS will really flush
# data on disk, some other OS will just try to do it ASAP.
#
# Redis supports three different modes:
#
# no: don't fsync, just let the OS flush the data when it wants. Faster.
# always: fsync after every write to the append only log. Slow, Safest.
# everysec: fsync only one time every second. Compromise.
#
# The default is "everysec", as that's usually the right compromise between
# speed and data safety. It's up to you to understand if you can relax this to
# "no" that will let the operating system flush the output buffer when
# it wants, for better performances (but if you can live with the idea of
# some data loss consider the default persistence mode that's snapshotting),
# or on the contrary, use "always" that's very slow but a bit safer than
# everysec.
#
# More details please check the following article:
# http://antirez.com/post/redis-persistence-demystified.html
#
# If unsure, use "everysec".# appendfsync always
appendfsync everysec
# appendfsync no

appendfsync用于设置同步的频率,其中频率是always > everysec > no,默认策略是everysec每秒刷新一次。

  • always:每次写入都进行同步
  • everysec:每秒钟同步一次
  • no:依据操作系统的同步策略,但是这个策略是不可控的

重写机制

当写入的数据多,此时.aof生成的文件就会很大,而且会出现冗余的问题,比如以下操作:

set key1 111
set key1 222
set key1 333
set key1 444

由于第四次写入覆盖了前三次的值,那么前三次操作就都是无效的,如果Redis真的每一条数据都保存下来,那么这个案例就多浪费了 3/4的空间。

为此Redis会对.aof文件进行重写,剔除文件中的冗余操作,合并一些操作,从而减小.aof文件的大小。

重写机制也分为手动触发和自动触发,如果想要手动触发,输入指令bgrewriteaof

自动触发要参照两个参数:

  • auto-aof-min-size:触发重写的最小大小,只有.aof超过该大小才触发重写,默认为64MB
  • auto-aof-rewrite-percentage:表示.aof当前占用的大小相比于上次重写增加的比例

重写流程如下:

在这里插入图片描述

和之前的bgsave类似,重写也是通过创建子进程完成的,子进程将当前内存中的所有数据,重写写入一个新的.aof文件,然后直接覆盖之前的.aof即可。

也就是说,重写的过程,并不是通过复杂的算法检测哪些内容重复,哪些可以合并。而是直接看当前的最终状态是什么,当前有什么就写入什么。

此处有一个步骤3.1,在子进程写入的过程中,父进程也会接收到数据,此时父进程会把数据写入到旧的.aof文件中。这主要是为了防止在重写.aof的过程中崩溃,一旦父子进程同时崩溃,那么就只能通过旧的.aof进行恢复,如果重写过程中不对旧的.aof更新,那么重写这段时间的数据就会丢失。

另外的,由于子进程创建时,只保存创建那一瞬间的父进程的内存状态,此时父进程接收到的后续的数据,子进程是看不到的。所以父进程还要通过3.2将数据写入一个中间缓存aof_rewrite_buf,将当前的新数据保存下来。

直到5.1子进程完成写入,给父进程发送一个信号,父进程就知道子进程写入完成了。随后通过5.2,把子进程重写期间收到的数据写入到新的.aof文件,最后再完成5.3文件的覆盖。


混合持久化

如果观察appendonlydir目录,会找到多个文件:

在这里插入图片描述

这内部同时包含.aof.rdb文件,这因为Redis采用了混合持久化的方式。

由于.aof文件是文本文件,加载速度很慢,为了提高AOF模式的加载速度,于是把.rdb的二进制存储模式引入了进来。每次进行重写的时候,会把当前的快照放到.rdb内部,以二进制的格式存储。而再重写之后到来的数据,存储.aof文件中,用于保持实时更新。

也就是说混合持久化综合了两者的优点,采用.rdb存储旧数据,提高加载效率。而,aof存储新来的数据,保证数据存储的及时性。每当重写时,把当前整个Redis的快照放到.rdb,而.aof存储重写期间到来的数据。


相关文章:

Redis:持久化

Redis&#xff1a;持久化 持久化RDBdump.rdb优缺点 AOF文件同步重写机制 混合持久化 持久化 虽然Redis是一个内存级别的数据库&#xff0c;但是Redis也是有持久化的能力的。当系统崩溃时&#xff0c;Redis就会被强制退出&#xff0c;此时内存中的数据就会丢失。为了能够在下次…...

精准监控,高效运营 —— 商品信息实时分析为商家带来新机遇

在现代商业环境中&#xff0c;精准监控和高效运营是商家成功的关键。通过实时分析商品信息&#xff0c;商家可以洞察市场趋势、优化库存管理、提升销售策略&#xff0c;从而抓住新的商业机遇。本文将介绍如何利用Python和一些流行的数据分析工具来实现商品信息的实时分析&#…...

Nginx应用配置实战

Nginx通用部署 Nginx常见参数介绍 Nginx 配置文件中的指令和参数决定了它的行为。下面详细介绍一些常见的 Nginx 参数&#xff0c;以帮助你更好地理解和配置 Nginx。 1. worker_processes worker_processes auto;作用&#xff1a;设置 Nginx 处理请求的工作进程数量。auto …...

html实现倒计时

参考网址 <!DOCTYPE html> <html> <head><title>倒计时示例</title> </head> <body><h1 id"titleCountDown"></h1><div id"countdown"></div><script>// 目标日期var targetDat…...

HTMLCSS练习

1) 效果如下 2) 代码如下 2.1) HTML <!DOCTYPE html> <html lang"en"> <head><meta charset"UTF-8"><meta http-equiv"X-UA-Compatible" content"IEedge"><meta name"viewport" conte…...

LeetCode讲解篇之377. 组合总和 Ⅳ

文章目录 题目描述题解思路题解代码题目链接 题目描述 题解思路 总和为target的元素组合个数 可以由 总和为target - nums[j]的元素组合个数 转换而来&#xff0c;其中j为nums所有元素的下标 而总和target - nums[j]的元素组合个数 可以由 总和为target - nums[j] - nums[k]的…...

Midjourney中文版:创意无限,艺术之旅由此启程

Midjourney中文版——一个将你的文字想象转化为视觉艺术的神奇平台。无需繁琐的绘画技巧&#xff0c;只需简单的文字描述&#xff0c;你就能开启一场前所未有的艺术之旅。 Midjourney AI超强绘画 (原生态系统&#xff09;用户端&#xff1a;Ai Loadinghttps://www.mjdiscord.c…...

安装R和RStudio:开始你的数据分析之旅

数据分析是当今世界中一个非常热门的领域&#xff0c;而R语言是进行数据分析的强大工具之一。R是一种编程语言和软件环境&#xff0c;用于统计计算和图形表示。RStudio是一个集成开发环境&#xff08;IDE&#xff09;&#xff0c;它为R语言提供了一个更加友好和高效的工作环境。…...

如何使用python连接数据库?

数据分析离不开数据库&#xff0c;如何使用python连接数据库呢&#xff1f;听我娓娓道来哈 该笔记参考了PyMySQL官方文档和《python数据采集》关于数据存储的部分&#xff0c;欢迎大家去阅读原著&#xff0c;相信会理解的更加透彻。 补充&#xff1a;文末增加Oracle数据库的连…...

停车位识别数据集 图片数量12416张YOLO,xml和txt标签都有; 2类类别:space-empty,space-occupied;

YOLO停车位识别 图片数量12416张&#xff0c;xml和txt标签都有&#xff1b; 2类类别&#xff1a;space-empty&#xff0c;space-occupied&#xff1b; 用于yolo&#xff0c;Python&#xff0c;目标检测&#xff0c;机器学习&#xff0c;人工智能&#xff0c;深度学习&#xff0…...

MySQL 创建子账号

1. 使用 root 账号登录 MySQL 使用 root 账号登录 MySQL&#xff0c;登录成功如图所示&#xff1a; 新建一个 MySQL 子账号&#xff0c;新建子账号命令如下&#xff1a; 命令 : CREATE USER testlocalhost IDENTIFIED BY 123456;若出现如下图所示&#xff0c;则表示新建 MySQL…...

代码随想录 106. 岛屿的周长

106. 岛屿的周长 #include<bits/stdc.h> using namespace std;int main(){int n, m;cin >> n >> m;vector<vector<int>> mp(n, vector<int>(m, 0));for (int i 0; i < n; i){for (int j 0; j < m; j){cin >> mp[i][j];}}in…...

阿里云融合认证中的App端一键登录能力

在如今的移动互联网环境中&#xff0c;App端的一键登录功能逐渐成为提升用户体验的关键。用户不再需要繁琐的注册流程或输入短信验证码&#xff0c;一键即可通过手机号码完成登录。而阿里云融合认证中&#xff0c;一键登录能力为移动应用提供了一个简单、便捷且安全的用户身份验…...

基于YOLO11/v10/v8/v5深度学习的安检X光危险品检测与识别系统设计与实现【python源码+Pyqt5界面+数据集+训练代码】

《博主简介》 小伙伴们好&#xff0c;我是阿旭。专注于人工智能、AIGC、python、计算机视觉相关分享研究。 ✌更多学习资源&#xff0c;可关注公-仲-hao:【阿旭算法与机器学习】&#xff0c;共同学习交流~ &#x1f44d;感谢小伙伴们点赞、关注&#xff01; 《------往期经典推…...

vue-插槽作用域实用场景

vue-插槽作用域实用场景 1.插槽1.1 自定义列表渲染1.2 数据表格组件1.3 树形组件1.4 表单验证组件1.5 无限滚动组件 1.插槽 插槽感觉知道有这个东西&#xff0c;但是挺少用过的&#xff0c;每次看到基本都会再去看一遍用法和概念。但是在项目里&#xff0c;自己还是没有用到过…...

Prometheus+Grafana 监控 K8S Ingress-Ningx Controller

文章目录 一、prometheus中添加ingress-nginx的服务发现配置二、ingress-nginx controller的service添加端口暴露监控指标三、grafana添加ingress-nginx controller的监控模版 ingress-nginx默认是没有开启监控指标的&#xff0c;需要我们在ingress-nginx controller的svc里面开…...

如何在Visual Studio 2019中创建.Net Core WPF工程

如何在Visual Studio 2019中创建.Net Core WPF工程 打开Visual Studio 2019&#xff0c;选择Create a new project 选择WPF App(.Net Core) 输入项目名称和位置&#xff0c;单击Create 这样我们就创建好了一个WPF工程 工程文件说明 Dependencies 当前项目所使用的依赖库&…...

自然语言处理(NLP)论文数量的十年趋势:2014-2024

引言 近年来&#xff0c;自然语言处理&#xff08;NLP&#xff09;已成为人工智能&#xff08;AI&#xff09;和数据科学领域中的关键技术之一。随着数据规模的不断扩大和计算能力的提升&#xff0c;NLP技术从学术研究走向了广泛的实际应用。通过观察过去十年&#xff08;2014…...

.net core API中使用LiteDB

LiteDB介绍 LiteDB 是一个小巧、快速和轻量级的 .NET NoSQL 嵌入式数据库。 无服务器的 NoSQL 文档存储简单的 API&#xff0c;类似于 MongoDB100% 的 C# 代码支持 .NET 4.5 / NETStandard 1.3/2.0&#xff0c;以单个 DLL&#xff08;不到 450KB&#xff09;形式提供线程安全…...

YOLO_V8分割

YOLO_V8分割 YOLO安装 pip install ultralytics YOLO的数据集转化看csdn 数据标注EIseg EIseg这块&#xff0c;正常安装就好&#xff0c;但是numpy和各类包都容易有冲突&#xff0c;python版本装第一点 数据标注过程中&#xff0c;记得把JSON和COCO都点上&#xff0c;把自…...

根据请求错误的状态码判断代理配置问题

SafeLine&#xff0c;中文名 “雷池”&#xff0c;是一款简单好用, 效果突出的 Web 应用防火墙(WAF)&#xff0c;可以保护 Web 服务不受黑客攻击。 雷池通过过滤和监控 Web 应用与互联网之间的 HTTP 流量来保护 Web 服务。可以保护 Web 服务免受 SQL 注入、XSS、 代码注入、命…...

Python 网络爬虫高阶用法

网络爬虫成为了自动化数据抓取的核心工具。Python 拥有强大的第三方库支持&#xff0c;在网络爬虫领域的应用尤为广泛。本文将深入探讨 Python 网络爬虫的高阶用法&#xff0c;包括处理反爬虫机制、动态网页抓取、分布式爬虫以及并发和异步爬虫等技术。以下内容结合最新技术发展…...

芯片Tapeout前GDS Review | Calibre中如何切出gds中指定区域版图?

在SoC芯片实现阶段我们会用到很多模拟IP&#xff0c;IO。对于这类模拟IP相关的电源连接&#xff0c;ESD保护电路连接&#xff0c;信号线连接都需要跟IP Vendor进行Review。但芯片整体版图涉及商业机密&#xff0c;我们不希望整个芯片的版图被各大vendor看到&#xff0c;因此我们…...

43 | 单例模式(下):如何设计实现一个集群环境下的分布式单例模式?

上两篇文章中&#xff0c;我们针对单例模式&#xff0c;讲解了单例的应用场景、几种常见的代码实现和存在的问题&#xff0c;并粗略给出了替换单例模式的方法&#xff0c;比如工厂模式、IOC 容器。今天&#xff0c;我们再进一步扩展延伸一下&#xff0c;一块讨论一下下面这几个…...

PHP如何解决异常处理

在PHP中&#xff0c;异常处理是通过使用try、catch、throw以及finally这几个关键字来实现的。以下是一个简单的介绍和示例&#xff1a; 异常处理的基本步骤 抛出异常&#xff1a; 使用throw关键字抛出一个异常对象。异常对象通常是Exception类或其子类的实例。 捕获异常&…...

C++ socket编程(3)

前面文章&#xff0c;介绍了一个简单socket通讯Demo&#xff0c; 客户端和服务器进行简单的交互。两个代码都很简单&#xff0c;如果情况一复杂&#xff0c;就会出错。这节我们把代码完善一下&#xff0c;实现一个客户端输入&#xff0c;发送&#xff0c;服务器echo的交互。本文…...

Collection-LinkedList源码解析

文章目录 概述LinkedList实现底层数据结构构造函数getFirst(), getLast()removeFirst(), removeLast(), remove(e), remove(index)add()addAll()clear()Positional Access 方法查找操作 概述 LinkedList同时实现了List接口和Deque接口&#xff0c;也就是说它既可以看作一个顺序…...

vue判断对象数组里是否有重复数据

TOCvue判断对象数组里是否有重复数据 try {//通过产品编码赛选出新的数组 在比较let names this.goodsJson.map(item > item["productCode"]);let nameSet new Set(names)if (nameSet.size ! names.length) {this.$message({message: 警告&#xff01;产品选项…...

CSS 3D转换

在 CSS 中&#xff0c;除了可以对页面中的元素进行 2D 转换外&#xff0c;您也可以对象元素进行 3D转换&#xff08;将页面看作是一个三维空间来对页面中的元素进行移动、旋转、缩放和倾斜等操作&#xff09;。与 2D 转换相同&#xff0c;3D 转换同样不会影响周围的元素&#x…...

51单片机数码管循环显示0~f

原理图&#xff1a; #include <reg52.h>sbit dulaP2^6;//段选信号 sbit welaP2^7;//位选信号unsigned char num;//数码管显示的数字0~funsigned char code table[]{ 0x3f,0x06,0x5b,0x4f, 0x66,0x6d,0x7d,0x07, 0x7f,0x6f,0x77,0x7c, 0x39,0x5e,0x79,0x71};//定义数码管显…...