【redis】什么是持久化之 RDB

什么是持久化

MySQL 的事务,有四个比较核心的特性:

  1. 原子性
  2. 一致性
  3. 持久性==>持久化(说的一回事)
  • 把数据存储在硬盘上==>持久
  • 把数据存在内存上==>不持久
  • 重启进程/重启主机之后,数据是否还存在
  1. 隔离性

Redis 是一个内存数据库,是把数据存在内存中的。内存中的数据并不是持久的,要想能做到持久,就需要让 Redis 把数据存储在硬盘上

Redis 相比于 MySQL 这样的关系型数据库,最明显的有点/优势==>效率高/快

  • 因为它的数据是存在内存上的

如何实现持久化

为了保证速度快,数据肯定还得再内存中,但是为了持久,数据还得想办法存储在硬盘上

  • redis 决定,内存和硬盘上都存数据
  • 这样的两份数据,理论上是完全相同的(实际上可能存在一个小的概率有差异,取决于我们具体怎么进行持久化)

  • 当要插入一个新的数据的时候,就需要把这个数据,同时写入内存和硬盘。
    • 实际上怎么写入硬盘,还有不同的策略,不会导致每次都要写两份,导致效率降低
  • 当查询某个数据的时候,直接从内存读取
  • 硬盘的数据只是在 redis 重启的时候,用来恢复内存中的数据的
    这样就既能保证高效,又能通过硬盘恢复数据,保证持久化的效果,代价就是消耗了更多空间(一份数据,存了两遍)(硬盘便宜,不会带来太多成本)

实现策略

  1. RDB --> Redis DataBase
  2. AOF --> Append Only FIle

RDB

定期的把我们 Redis 内存中的数据,都给写入硬盘中,生成一个“快照

  • Redis 给内存中当前存储的这些数据,赶紧拍个照片,生成一个文件,存储在硬盘中
  • 后续 Redis 一旦重启了(内存数据就没了),就可以根据刚才的“快照”,把内存中的数据给恢复回来

[!quote] 快照
某个案发现场,警察来了之后,会拉上警戒线,然后开始忙碌地拍照,记录现场==>后续就可以根据这些记录的照片,来还原出现场当前发生了什么

定期”具体又分为两种方式:

  1. 手动触发
    • 程序员通过 Redis 客户端,执行特定的命令,来触发快照生成(savebgsave
  2. 自动触发
    • Redis 配置文件中,设置一下,让 Redis 每隔多长时间/每产生多少次修改就出发

手动触发

执行 save 的时候,Redis 就会全力以赴的进行“快照生成”操作,此时就会阻塞 Redis 的其他客户端的命令

  • 类似于 keys * 的后果
  • 一般不建议使用

save 是在前台,bgsavebackground)是在后面偷摸进行,不会影响 Redis 服务器处理其他客户端的请求和命令

  • 这样既可以保证持久化
  • 又可以保证 Redis 可以正常去响应命令

bgsave

Redis 是怎么做到 bgsave 的呢?是不是偷偷搞了个多线程?

  • 并非如此,多线程是实现并发编程的场景的一种方式,但不是唯一
  • Redis 使用的是“多进程”的方式,来完成的并发编程,实现 bgsave

image.png

Redis 服务器(父进程)收到 bgsave 的命令之后,首先会进行一个判断

1 . 判定当前是否已经存在其他正在工作的子进程

比如现在已经有一个子进程正在执行 bgsave,此时就直接把当前的 bgsave 返回


2 . 如果没有其他的工作子进程,就通过 fork 这样的系统调用,创建一个子进程来

forkLinux 系统提供的一个创建子进程的 API

  • 如果是其他系统,比如 Windows,创建子进程就不是 forkCreatProcess
  • fork 创建子进程,简单粗暴,就是直接把当前的进程(父进程)复制一份,作为子进程。一旦复制完成了,父子进程就是两个独立的进程,就格子执行各自的了
    • 会复制 PCB、虚拟地址空间(内存中的数据)、文件描述附表…
    • 本来 redis server 中,有若干变量,保存了一些键值对数据。随着这样的 fork 的进行,子进程的这个内存里也会存在和刚才父进程中一模一样的变量

因此,复制出来的“克隆体“(子进程),内存中的数据就是和“本体”(父进程)是一样的。接下来安排子进程去进行“持久化”操作,也就相当于把父进程本体这里的数据给持久化了

父进程打开了一个文件,fork 了之后,子进程也是可以同时使用这个文件的

  • 导致了子进程持久化写入的那个文件,和父进程本来要写的文件是同一个

如果当前 redis 服务器中存储的数据特别多,内存消耗特别大,此时进行上述的复制操作,是否会有很大的性能开销?

  • 此处的性能开销其实挺小
  • fork 在进行内存拷贝的时候,不是简单无脑的直接把所有的数据都拷贝一遍,而是“写实拷贝”的机制来完成的
    • 如果子进程里的这个内存数据,和父进程的内存数据完全一样,此时就不会触发真正的拷贝动作(而是爷俩其实用一份内存数据)
    • 但是,其实这俩进程的内存空间,应该是各自独立的。一旦某一方针对这个数据进行了修改,就会立即触发真正的物理内存上的数据拷贝

在进行 bgsave 这个场景中,绝大部分的内存数据,是不需要进行改变的(整体来说这个过程执行的还挺快,这个短时间内,父进程中不会有大批的内存数据变化)

因此,子进程的“写实拷贝”不会触发很多次,也就保证了整体的“拷贝时间”是可控的,高效的


  1. 子进程负责进行写文件,生成快照的过程,父进程继续接收客户端的请求,继续正常提供服务

  1. 子进程完成整体的持久化过程之后,就会通知父进程干完了,父进程就会更新一些统计信息,子进程就可以结束销毁了

总结:
创建子进程,子进程完成持久化操作,持久化会把数据写入到新的文件中,然后使用新的文件替换旧的文件

  • 子进程不好观察,我们观察新旧文件(通过 stat 命令,查看文件的 inode 号)

RDB 文件

redis 生成的 RDB 文件,是放在 redis 的工作目录中的,也是在 redis 配置文件中进行设置的

image.png

  • RDB 机制生成的镜像文件,redis 服务器默认就是开启了 RDB
  • 这是一个二进制文件,把内存中的数据,以压缩(消耗一定 CPU 资源,但是能省空间)的形式,保存到这个二进制文件中
    • 最多打开看看就行了,不要乱改,一旦要是把数据的格式改坏了,就麻烦了
    • 后续 redis 服务器重新启动,就会尝试加载这个 RDB 文件,如果发现格式错误,就可能会加载数据失败

redis 提供了 RDB 文件的检查工具image.png|256

当执行生成 RDB 镜像操作的时候,此时就会把要生产的快照数据,先保存到一个临时文件中。当这个快照生成完毕之后,再删除之前的 RDB 文件,把新生成的临时的 RDB 文件名字改成刚才的 dump.rdb

  • 自始至终,RDB 文件始终只有一个

效果

RDB 文件中的数据,不是你这边插入了数据,就会立即更新的

  • image.png|438
  • 插入数据之后,观察 RDB 文件内容 image.png image.png|427
  • 发现没有变化,此时我们执行保存数据的命令image.png
    image.png|331

可以发现 RDB 文件内容更新了


RDB 的触发时机:

  1. 手动(save、bgsave)
  2. 自动(配置文件中,进行设置)

image.png

  • 900s 之后,并且至少存在一次 key 的修改,就会触发自动更新

这些数值都是可以自由修改的,但是此处修改数据的时候,有一个基本的原则:

  • 生成一次 RDB 快照,这个成本较高,不能让这个操作执行太频繁

redis 持久化生成快照操作,不仅仅是手动执行命令才出发,也可以自动触发

  1. 通过刚才配置文件中 save 执行 M 时间内,修改 N
  2. 通过 shutdown 命令(redis 里的一个命令)关闭 redis 服务器,也会触发(service redis-server restart)(正常关闭
  3. redis 进行主从复制的时候,主节点也会自动生成 RDB 快照,然后把 RDB 快照文件内容传输给从节点
  • 如果是通过正常流程重新启动 redis 服务器,此时 redis 服务器会在退出的时候,自动触发生成 RDB 操作
  • 但如果是异常重启(kill -9 或者服务器掉电),此时 redis 服务器来不及生成 RDB,内存中尚未保存到快照中的数据,就会随着重启而丢失
  • 若要修改 RDB 配置,修改完成后需要重启服务器
  • 如果 RDB 文件被改坏了,redis 服务器启动不了了,我们可以去看一下日志,查看报错信息

redis 提供了 RDB 文件的检查工具,可以先通过检查工具,检查一下 RDB 文件格式是否符合要求 image.png|301

  • 检查工具和 reids 服务器,在 5.0 版本是同一个可执行程序,但是我们可以在运行的时候加上不同选项
  • 在运行的时候,加上 RDB 文件作为命令行参数,此时就是以检查工具的方式来运行

image.png

  • 这里就显示 RDB 文件里面有错误

RDB 小结

  • RDB 是一个紧凑压缩的二进制文件,代表 redis 在某个时间点上的数据快照。非常适用于备份,全量复制等场景。比如每 6 小时执行 bgsave 备份,并把 RDB 文件复制到远程机器或者文件系统中(如 hdfs)用于灾备
  • redis 加载 RDB 恢复数据远远快于 AOF 的方式
    • RDB 是使用二进制的方式来组织数据,直接把数据读取到内存中,按照字节的格式取出来,放到结构体/对象中即可
    • AOF 是使用文本的方式来组织数据
  • RDB 方式数据没办法做到实时持久化,因为 bgsave 每次运行都要执行 fork 创建子进程,属于重量级操作,频繁执行成本过高
  • RDB 文件使用特定二进制格式保存,redis 版本演进过程中有多个 RDB 版本,兼容性可能有风险
    • 老版本的 redisRDB 文件,放到新版本的 redis 中不一定能识别

如果确实需要有一些“升级版本”的需求,就可以通过写一个程序的方式,直接遍历旧的 redis 中的所有 key,把数据取出来,插入到新的 redis 服务器中即可

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

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

相关文章

Python 鼠标轨迹算法 - 防止游戏检测

一.简介 鼠标轨迹算法是一种模拟人类鼠标操作的程序,它能够模拟出自然而真实的鼠标移动路径。 鼠标轨迹算法的底层实现采用C/C语言,原因在于C/C提供了高性能的执行能力和直接访问操作系统底层资源的能力。 鼠标轨迹算法具有以下优势: 模拟…

游戏立项时期随笔记录(1)

模拟经营的项目还没有完全结束,这几天又有可能涉及到一个新项目。感想随笔记录一下,防止忘记。今天一天整理这个,搞得今天没时间看数学和AI。 在 Unity3D 游戏前端主程序的立项时期,核心目标是明确技术方向、评估可行性、搭建基础…

Channel-wise Knowledge Distillation for Dense Prediction论文阅读和

paper:https://arxiv.org/pdf/2011.13256.pdf code:https://github.com/open-mmlab/mmrazor 这篇paper主要是商汤开源的mmrazor中提及在detection有效果,我之前记录的几篇sota文章虽然在各自的paper中在detection领域都有提及有增益&#…

hide函数的使用方法

在编程中,我们常常需要控制元素的显示与隐藏。特别是在前端开发中,hide 函数是一个非常常见的操作,尤其是在 JavaScript 和 jQuery 中。它可以让你轻松地将元素从视图中隐藏,进而提升用户交互体验和页面的响应能力。本文将介绍如何…

【MySQL】基本操作 —— DML 与约束

目录 DML 基本介绍DML 常见操作添加数据 insert给指定字段添加数据给全部字段添加数据给指定字段批量添加数据给全部字段批量添加数据 修改数据 update删除数据 delete 约束基本概念约束操作主键约束添加单列主键添加多列主键(联合主键)修改表结构添加主…

nginx配置转发到另一个网站或另一台服务器的服务

需求背景 在一台服务器上安装了一个服务,不想使用ip:port方式,想使用域名打开这个服务的地址。 1. 配置转发 1.1 参数解释 listen:指定 Nginx 监听的端口。在上面的例子中,Nginx 监听 8888 端口。server_name:用于…

HarmonyOS三层架构实战

目录: 1、三层架构项目结构1.0、三层架构简介1.1、 common层(主要放一些公共的资源等)1.2、 features层(主要模块定义的组件以及图片等静态资源)1.3、 products层(主要放主页面层和一些主要的资源&#xff…

macOS homebrew - 切换源

https://mirrors.tuna.tsinghua.edu.cn/help/homebrew/ 环境变量中 添加: export HOMEBREW_BREW_GIT_REMOTE"https://mirrors.tuna.tsinghua.edu.cn/git/homebrew/brew.git" export HOMEBREW_CORE_GIT_REMOTE"https://mirrors.tuna.tsinghua.edu.cn…

ETL中的实用功能以及数据集成方式

在企业数字化转型的进程中,数据集成扮演着至关重要的角色。它不仅是实现信息流动和系统协同的关键步骤,更是提升企业运营效率和决策能力的核心驱动力。ETL(Extract,Transform,Load)作为数据集成的重要工具&…

基于Springboot+Typst的PDF生成方案,适用于报告打印/标签打印/二维码打印等

基于SpringbootTypst的PDF生成方案,适用于报告打印/标签打印/二维码打印等。 仅提供后端实现 Typst2pdf-for-report/label/QR code github 环境 JDK11linux/windows/mac 应用场景 适用于定制化的报告模板/标签/条码/二维码等信息的pdf生成方案。通过浏览器的p…

OSG简介

OSG OpenSceneGraph (简称 OSG) 是一个开源的高性能3D图形库。 作用 它为开发者提供了一个强大的API,处理和渲染复杂的3D图形。 特点 OSG基于OpenGL构建,提供了对现代图形技术的支持,如着色器、纹理映射、光照模型等高级特性。 跨平台支…

简述下npm,cnpm,yarn和pnpm的区别,以及跟在后面的-g,--save, --save-dev代表着什么

文章目录 前言一、npm,cnpm,yarn和pnpm的基本介绍和特点1.npm (Node Package Manager)2. Yarn3. cnpm (China npm)4. pnpm 二、简述npm和pnpm 的存储方式和依赖数1.存储方式2.依赖树 三、两者依赖树的差异导致结果的对比四、简单说说-g,--sav…

三分钟掌握视频剪辑 | 在 Rust 中优雅地集成 FFmpeg

前言 在当今的短视频时代,高效的视频剪辑已成为内容创作者和开发者的迫切需求。无论是裁剪视频开头结尾、提取高光时刻,还是制作 GIF、去除广告,剪辑都是必不可少的一环。 然而,批量处理大量视频并非易事,常见的挑战…

Python 视频爬取教程

文章目录 前言基本原理环境准备Python安装选择Python开发环境安装必要库 示例 1:爬取简单直链视频示例 2:爬取基于 HTML5 的视频(以某简单视频网站为例) 前言 以下是一个较为完整的 Python 视频爬取教程,包含基本原理…

ollama搭建deepseek调用详细步骤

在使用 Ollama 搭建 DeepSeek 并投喂数据的过程中,你需要几个主要步骤来确保一切顺利进行。以下是详细的指南,涵盖了从准备工作到实际投喂数据的所有环节。 准备环境确保你的计算机具备足够的硬件资源: CPU: 至少8核处理器(推荐12核以上)内存: 至少32GB RAM(推荐64GB以上…

VSCode C/C++ 开发环境完整配置及常见问题(自用)

这里主要记录了一些与配置相关的内容。由于网上教程众多,部分解决方法并不能完全契合我遇到的问题,因此我选择以自己偏好的方式,对 VSCode 进行完整的配置,并记录在使用过程中遇到的问题及解决方案。后续内容也会持续更新和完善。…

如何搭建一个安全经济适用的TRS交易平台?

TRS(总收益互换)一种多方参与的投资方式,也是绝对收益互换(total return swap)的一种形式。 它是一种衍生合约,是一种金融衍生品的合约,是指交易双方在协议期间将参照资产的总收益转移给信用保…

SpringMVC(四)Restful软件架构风格

目录 ​编辑 API接口设计的架构风格 一 Dao层实现(处理数据库) 二 Sercice层实现(处理业务逻辑) 三 Controller层(处理http请求) 四 补充知识点 1 PathVariable - 路径变量 2 CrossOrigin(Origins …

Docker搭建MySQL主从服务器

一、在主机上创建MySQL配置文件——my.cnf master服务器配置文件路径:/data/docker/containers/mysql-cluster-master/conf.d/my.cnf slave服务器配置文件路径: /data/docker/containers/mysql-cluster-master/conf.d/my.cnf master服务配置文件内容 …

鸿蒙路由 HMrouter 配置及使用一

1、学习链接 HMRouter地址 https://gitee.com/hadss/hmrouter/blob/dev/HMRouterLibrary/README.md 2、工程配置 下载安装 ohpm install hadss/hmrouter 添加编译插件配置 在工程目录下的build-profile.json5中,配置useNormalizedOHMUrl属性为true (我这项目创…