【Redis-04】Redis两种持久化方式(RDB和AOF)

news2025/1/11 22:37:38

 Redis是基于内存的数据结构服务器,保存了大量的键值对数据,所以持久化到磁盘是非常必要的,Redis提供了两种持久化的方式,分别是RDB和AOF。下面我们看下这两种持久化方式的具体实现原理。

1.RDB持久化

 首先,RDB持久化方式会产生一个经过压缩的二进制文件,Redis服务器在启动之初,通过这个文件可以还原数据库的状态。那么我们接下来看下RDB文件是如何实现保存和载入的。

1.1 RDB文件的保存

 RDB文件的保存有两个命令可以实现,分别是savebgsave,执行后都会生成新的RDB文件,区别是save会阻塞服务器的进程,直到RDB文件创建完成为止,期间服务器不能处理任何客户端的命令请求。而bgsave通过派生出一个子进程,由子进程来完成RDB文件的创建,期间服务器正常处理客户端的命令请求。其实这两个命令的底层实现方式都一样,只不过一个是主进程来做,另一个是通过子进程来完成。
 在redis.conf文件中,有两个参数是和rdb的文件保存相关:

// 这个是rdb文件的名称
dbfilename dump.rdb

// 这个是rdb文件的保存路径,这是相对路径,相对于redis-server的启动路径
dir ./

1.2 RDB文件的载入

 在redis服务器启动之初,会去查找有没有rdb的持久化文件存在,如果有就会自动载入,当然前提是没有开启aof持久化的功能。在rdb载入期间会,服务器处于阻塞装填,直到载入工作完全结束。

1.3 RDB持久化时服务器的状态

  1. save命令执行期间,所有客户端命令都会被拒绝执行。
  2. bgsave命令执行期间,客户端发送的savebgsave命令会被拒绝执行,但是客户端发送的bgrewriteaof不会拒绝但会被阻塞,直到当前的bgsave命令执行完毕。但是值得说明的是,如果服务器在执行bgrewriteaof命令期间,客户端发送的bgsave命令会被服务器拒绝。当然这是站在性能角度考虑,否则fock出两个子进程,大量的进行磁盘的读写,会影响整个服务器的性能。

1.4 RDB持久化策略

 用户可以通过配置文件给RDB的持久化设置保存策略,看一下redis.conf文件中的配置:

save 900 1
save 300 10
save 60 10000

 以上的默认配置可以表示为:服务器在900秒之内,至少进行了1次的修改,在300秒之内至少进行了10次修改,在60秒之内至少进行了10000次修改。这三种策略只要满足一个,即可触发RDB的持久化。
 这里需要了解一下,Redis是怎么基于这些配置策略实现自动化间歇性保存RDB文件的,还是回到RedisServer这个这个结构体的源码中看一下:

struct redisServer {
    // 数组,用于保存redis.conf配置的持久化策略
    struct saveparam *saveparams;   /* Save points array for RDB */
    // 上面这个数组的长度
    int saveparamslen;              /* Number of saving points */
    // 记录上一次持久化到现在服务器修改了多少键值对
    long long dirty;                /* Changes to DB from the last save */
    // 记录上一次RDB持久化的UNIX时间戳
    time_t lastsave;                /* Unix time of last successful save */
}

 在redisServer中,有saveparams数组专门保存我们配置的持久化策略,这里使用到了saveparam这个结构体,看一下源码:

struct saveparam {
	// 这里是配置文件save的第1个参数
    time_t seconds;
    // 这里是配置文件save的第2个参数
    int changes;
};

 这样,配置文件中的持久化策略就记录到了redisServer.saveparam属性中,还是会基于serverCron这个时间事件函数,100ms执行一次,每次会检查 dirtylastsave 记录的修改键值对数量和时间差,是否匹配到了saveparam中配置的持久化策略,如果命中就进行新一轮的RDB持久化。

2.AOF持久化

 和RDB不同,AOF是通过记录Redis服务器中执行的写命令来记录数据库状态的,类似于mysql的binlog,当然保存的内容是经过协议转换的命令。在服务器启动之初,通过载入和执行AOF文件中的命令来还原数据库的状态。

2.1 持久化的实现

 在服务器执行命令之后,并不是立刻写入aof文件中,而是先写入 aof_buf缓冲区里面,这也是redisServer的一个属性结构:

struct redisServer {
    // aop缓冲区,记录服务器写入的命令
    sds aof_buf;      /* AOF buffer, written before entering the event loop */
}

 我们再看一下redis.conf关于aof持久化的一个配置:

// 这个表示每次执行都会写入
# appendfsync always
// 这个表示每秒写入一次
appendfsync everysec
// 这个由操作系统决定,无法控制
# appendfsync no

 AOF实现持久化的原理是这样的,客户端执行的命令会先记录到 redisServer.aof_buf 中,然后基于配置文件的appendfsync策略决定什么时候同步到AOF文件中。这里的同步也会经过两个步骤:

  1. aof_buf 内容写入到操作系统文件缓存 pagecache
  2. pagecache 落盘写入到屋里磁盘设备中;

 我们知道Redis是基于Reactor网络模型,不断进行事件循环,每进行一轮的事件循环,都会执行步骤1,所以从aof_buf 到 pagecache总是会发生。但是步骤2就跟appendfsync有关系了:

  • always表示只要步骤1发生,步骤2也会发生,所以是最安全,但是效率最慢的一个。
  • everysec表示步骤1发生后,步骤2每秒执行一次落盘,是效率和数据安全折中的方案,停机故障时有丢失1秒钟数据的风险。
  • no表示步骤1发生后,何时落盘由操作系统决定,数据丢失风险大,效率也一般,因为数据量过大,单次落盘的时间也最长。

 默认配置是everysec,即每秒执行一次数据落盘保存。

2.2 文件的载入与数据还原

 因为AOF文件中包含了重建数据库状态的所有写命令,所以服务器只要读入并全部执行一遍就可以完成数据库状态的还原。服务器在启动之初,会创建一个不带网络连接的伪客户端来做这件事,在载入命令完成后,这个客户端的使命就结束了。

2.3 AOF文件的重写

 随着写入到AOF文件的命令越来越多,这个文件体积会越来大,会对宿主机或文件还原造成一定的影响,所以需要通过AOF文件的重写来解决文件体积膨胀的问题。
 AOF文件重写并不是对现有AOF文件进行处理,而是基于数据库当前的状态来实现的。服务器会从数据库中读取键对应的值,然后用一条命令去记录键值对,代替之前可能存在的多条命令,写入到一个新的AOF文件中,这就是AOF重写功能实现的原理。需要注意的是,对于某些元素比较多的集合或者列表(默认配置是64个),这个一条命令可能拆分成多条实现,避免造成客户端输入缓冲区溢出的情况。
 和bgsave一样,AOF重写的动作也是放到子进程去执行,这样可以保证父进程可以继续处理名请求。但是这里会有一个问题,就是AOF文件重写期间,父进程处理命令请求之后,会和重写AOF文件时的数据库状态不一致。Redis解决这个问题的方法是设置一个AOF重写缓冲区,子进程一单创建并且开始重写命令之后,父进程处理的所有写命令请求都会记录到AOF重写缓冲区。当子进程重写工作完成之后,会生成一个新的AOF文件,向父进程发送一个信号,父进程在接受此信号,开始执行以下工作:

  1. AOF重写缓冲区的内容写入到新的AOF文件中,保证新文件和服务器当前的状态一致;
  2. 对新的AOF文件改名,并原子的替换现有的AOF文件,完成新旧文件的替换。

 以上两步,父进程会造成服务器进程的阻塞,但其他时间,都不会阻塞,整个重写动作对服务器性能的影响降到了最低,以上就是bgrewriteaof命令的实现原理。

在这里插入图片描述

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

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

相关文章

Mysql基础

Mysql基础1. 数据库相关概念1.1 数据库1.2 数据库管理系统1.3 常见的数据库管理系统1.4 SQL2. Mysql的安装2.1 MySQL数据模型3. SQL概述3.1 SQL简介3.2 通用语法3.3 SQL分类4. DDL:操作数据库4.1 数据库的显示讲解4.2 查询4.3 创建数据库4.4 删除数据库4.5 使用数据库4.6 小结5…

linux Qt编译自己的动态库(.so),详细全流程

本篇记录Qt编译动态库全流程 1. 建立工程 首先,打开Qt,新建C Library 工程 点击choose之后,输入项目名称为Example,一直下一步即可 生成的项目里边有三个文件,分别是example.h, Example_global.h, example.cpp exam…

数据结构之:递归思想

(一)递归概念 将复杂问题 递推分解为最简问题 然后将结果回归的过程 Windows - Linux Linux Linux is not Unix 使用方法: 自己调用自己(二)斐波那契数列 兔子问题 有一对大兔子 每个月繁衍 一对小兔子(一…

【Java 设计模式】UML 之类图

UML 之类图前言:什么是 UML ?1 类图概念2 类的表示方式3 类与类之间关系的表示方式3.1 关联关系3.1.1 单向关联3.1.2 双向关联3.1.3 自关联3.2 聚合关系3.3 组合关系3.4 依赖关系3.5 继承关系3.6 实现关系前言:什么是 UML ? 定义…

Linux 软件包下载加速工具:APT Proxy

本篇文章将继续介绍这个仅有 2MB 身材大小的 Linux 软件包缓存和加速工具:APT Proxy。 相比老牌的 apt cacher ng 而言,除了尺寸更小、内存占用更低(10M以内)、它还拥有无需配置,开箱即用等特点。 写在前面 年中的时…

!与~有什么区别

目录 将整型数据转换为二进制的函数 利用函数查看!与~之后的数据有何不同 以一个非0数据作为例子 以0作为例子 我们都知道!与~都是用于取反的。那么这两个有什么区别呢? 我们百度结果如下,很明显,八股文。我接下…

element-ui时间选择器(DatePicker )数据回显

系列文章目录 第一篇【element-ui】table表格底部合计自定义配置 目录 前言 一、element-ui时间选择器(DatePicker )是什么? DatePicker 日期选择器 二、返回数据格式 1.引入 总结 前言 需求:element-ui时间选择器&#…

【报错】QT Release NO CMAKE_CXX_COMPILER could be found

NO CMAKE_CXX_COMPILER could be found 错误: Tell CMake where to find the compiler by setting either the environmentvariable "CC" or the CMake cache entry CMAKE_C_COMPILER to the full path tothe compiler, or to the compiler name if it …

PostgreSQL数据库动态共享内存管理器——dynamic shared memory segment

首先看dynamic_shared_memory_type GUC参数,该参数用于指定dynamic shared memory implementation类型(DSM_IMPL_POSIX、DSM_IMPL_SYSV、DSM_IMPL_WINDOWS、DSM_IMPL_MMAP,定义在src/include/storage/dsm_impl.h文件中)。了解一下…

前段入门-CSS

目录1 CSS 快速入门1.1 CSS 的介绍1.2 CSS 的组成2 基本语法2.1 CSS 的引入方式2.1.1 内联样式2.1.2 内部样式2.1.3 外部样式2.2 注释2.3 选择器2.3.1 基本选择器2.3.2 属性选择器2.3.3 伪类选择器2.3.4 组合选择器2.4 总结3 CSS 案例-头条页面3.1 案例效果3.2 案例分析3.2.1 边…

【第三部分 | 移动端开发】4:Rem布局

目录 | Rem布局简介 | 单位 rem | 媒体查询 | 根据不同的媒体引入不同的CSS | less基础 概述与安装 基础使用:创建less文件 基础使用:变量 基础使用:用Esay LESS插件把less文件编译为css 基础使用:嵌套 基础使用&#x…

cuda在windows10安装教程

CUDA安装教程,以Windows10系统为例: CUDA.exe安装 查看电脑的支持的CUDA版本,按照如下教程: 首先找到这个图标,也就是nvidia控制面板,然后打开: 然后点击左下角系统信息 再点击“组件”&…

LabVIEW性能和内存管理 8

LabVIEW性能和内存管理 8 本文介绍LabVIEW性能和内存管理的几个建议8。 MemoryFragmentation内存碎片 内存管理器分配和释放内存需要时间,这会降低执行速度。在某些情况下,即使假设有足够的可用内存,也会发生内存不足错误。 上图显示了实际…

【练拳不练功,到老一场空】深入浅出计算机组成原理

深入浅出计算机组成原理 文章目录深入浅出计算机组成原理计算机的基本组成硬件设备组成CPU内存主板I/O 设备硬盘显卡冯.诺依曼体系结构运算器/处理器单元控制器存储器输入设备输出设备举个栗子:计算机的性能与功耗响应时间吞吐率CPU时钟/主频计算机的功耗计算机的指…

jdk8新特性(Lambda、Steam、函数式接口)

JDK8新特性 JDK8新特性Lambda表达式函数式(Functional)接口方法引用与构造器引用方法引用构造器引用强大的 StreamAPI创建Stream方式Stream 的中间操作Stream 的终止操作Optional 类Java 8 (又称为jdk 1.8)是Java语言开发的一一个主要版本。 Java 8是ora…

Electron 之通讯模块ipcMain 和 ipcRenderer

Electron一个使用HTML、CSS和JavaScript开发桌面应用程序的框架。Electron可以生成在Windows、macOS和Linux上运行的应用程序,借助Electron可以把我们的web端应用直接移植到桌面端而无需再次开发,这样我们可以使用同一套代码在不同平台上运行应用&#x…

数据收集面可视化

数据收集面可视化(Data Collector Surface Visualization)分析选项允许用户指定模型中的某一表面,在光线追迹的过程中收集光线数据,并显示或者输出该面的照度(或相关的物理量)。该分析选项允许计算&#xf…

电脑网页打不开提示错误err connection怎么办?

网页打不开显示err_connection_reset网络错误,怎么解决err_connection_reset网络错误?下面我们就来看看解决电脑err_connection_reset网络错误的方法,请看下文详细介绍。 方法一:组件注册 1、我们点下键盘的winR,输入…

2. 选择排序

2.1 内存的工作原理 需要将数据存储到内存时,你请求计算机提供存储空间,计算机给你一个存储地址。 需要存储多项数据时,有两种基本方式——数组和链表。 2.2 数组和链表 有时候,需要在内存中存储一系列元素。 使用数组意味着所…

ElasticSearch面试

Welcome to Elastic Docs | Elastic 1. ES的结构和底层实现 ES的整体结构? 一个 ES Index 在集群模式下,有多个 Node (节点)组成。每个节点就是 ES 的Instance (实例)。每个节点上会有多个 shard (分片)&#xff0…