Redis:持久化
Redis:持久化
- 持久化
- RDB
- dump.rdb
- 优缺点
- AOF
- 文件同步
- 重写机制
- 混合持久化
持久化
虽然Redis
是一个内存级别的数据库,但是Redis
也是有持久化的能力的。当系统崩溃时,Redis
就会被强制退出,此时内存中的数据就会丢失。为了能够在下次重启时恢复数据,Redis
会把数据在硬盘中备份一份,也就是说Redis
持久化的目的不是为了保存更多的数据,而是为了恢复数据。
Redis
有两种处理持久化的方式,RDB
和AOF
,两者的区别可以简单理解如下:
RDB
:定期同步内存与硬盘的数据AOF
:只要内存的数据被修改,立刻同步到硬盘
本博客就基于这两种方式,讲解Redis
的持久化。
RDB
RDB
全称Redis DataBase
,用于持久化Redis
中的数据,其会定期把Redis
的数据保存下来,这份数据就称为一个快照
,随后存储到硬盘中。
除了等到指定时间,让其自动生成快照,RDB
还支持程序员通过指令生成快照:
save
:此时Redis
会立刻生成快照,但是由于Redis
是单线程模型,其它的所有操作都会被阻塞bgsave
:Redis
立刻生成快照,但是是在后台运行,不会影响其他操作
在实际开发中,一般都使用bgsave
,而不是save
。此时就有疑问了,Redis
不是单线程模型吗?如何做到在后台生成快照,而不影响其他操作的?
其实Redis
在这使用了多进程的模式,流程如下:
当用户执行bgsave
,此时父进程通过fork
创建子进程,随后子进程去完成快照生成,父进程继续响应其他命令。当子进程持久化完毕,就给父进程发送信号通知父进程。如果父进程在收到信号之前,收到了来自其他用户的bgsave
命令,此时不做处理直接返回,因为已经有子进程正在进行持久化了,此时多个bgsave
命令只执行一次持久化。
此处的fork
是Linux
的一个系统调用,因为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
的意思就是:
- 如果在
3600 s
内修改了1
次数据,3600
秒后更新dump.rdb
- 如果在
300 s
内修改了100
次数据,300
秒后更新dump.rdb
- 如果在
60 s
内修改了10000
次数据,60
秒后更新dump.rdb
另外的,如果配置save “”
,也就是加一个空字符串,相当于禁止通过该方式自动更新。
除此之外,Redis
还有一些其他方式也会自动生成快照: 0
- 通过配置文件的
save
属性,定期生成快照 Redis
正常关闭时- 进行主从复制时
- 执行
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
可以看到很多认识指令,比如SELECT
,XADD
,MAXLEN
。
那么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:持久化 持久化RDBdump.rdb优缺点 AOF文件同步重写机制 混合持久化 持久化 虽然Redis是一个内存级别的数据库,但是Redis也是有持久化的能力的。当系统崩溃时,Redis就会被强制退出,此时内存中的数据就会丢失。为了能够在下次…...

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

Nginx应用配置实战
Nginx通用部署 Nginx常见参数介绍 Nginx 配置文件中的指令和参数决定了它的行为。下面详细介绍一些常见的 Nginx 参数,以帮助你更好地理解和配置 Nginx。 1. worker_processes worker_processes auto;作用:设置 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]的元素组合个数 转换而来,其中j为nums所有元素的下标 而总和target - nums[j]的元素组合个数 可以由 总和为target - nums[j] - nums[k]的…...

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

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

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

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

MySQL 创建子账号
1. 使用 root 账号登录 MySQL 使用 root 账号登录 MySQL,登录成功如图所示: 新建一个 MySQL 子账号,新建子账号命令如下: 命令 : CREATE USER testlocalhost IDENTIFIED BY 123456;若出现如下图所示,则表示新建 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端一键登录能力
在如今的移动互联网环境中,App端的一键登录功能逐渐成为提升用户体验的关键。用户不再需要繁琐的注册流程或输入短信验证码,一键即可通过手机号码完成登录。而阿里云融合认证中,一键登录能力为移动应用提供了一个简单、便捷且安全的用户身份验…...

基于YOLO11/v10/v8/v5深度学习的安检X光危险品检测与识别系统设计与实现【python源码+Pyqt5界面+数据集+训练代码】
《博主简介》 小伙伴们好,我是阿旭。专注于人工智能、AIGC、python、计算机视觉相关分享研究。 ✌更多学习资源,可关注公-仲-hao:【阿旭算法与机器学习】,共同学习交流~ 👍感谢小伙伴们点赞、关注! 《------往期经典推…...

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

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

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

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

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

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

根据请求错误的状态码判断代理配置问题
SafeLine,中文名 “雷池”,是一款简单好用, 效果突出的 Web 应用防火墙(WAF),可以保护 Web 服务不受黑客攻击。 雷池通过过滤和监控 Web 应用与互联网之间的 HTTP 流量来保护 Web 服务。可以保护 Web 服务免受 SQL 注入、XSS、 代码注入、命…...

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

芯片Tapeout前GDS Review | Calibre中如何切出gds中指定区域版图?
在SoC芯片实现阶段我们会用到很多模拟IP,IO。对于这类模拟IP相关的电源连接,ESD保护电路连接,信号线连接都需要跟IP Vendor进行Review。但芯片整体版图涉及商业机密,我们不希望整个芯片的版图被各大vendor看到,因此我们…...

43 | 单例模式(下):如何设计实现一个集群环境下的分布式单例模式?
上两篇文章中,我们针对单例模式,讲解了单例的应用场景、几种常见的代码实现和存在的问题,并粗略给出了替换单例模式的方法,比如工厂模式、IOC 容器。今天,我们再进一步扩展延伸一下,一块讨论一下下面这几个…...

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

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

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

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

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

51单片机数码管循环显示0~f
原理图: #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};//定义数码管显…...