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

Redis学习[3] ——持久化

四. Redis 持久化

4.1 Redis 如何保证数据不丢失?

由于Redis的数据是保存在内存中,而内存中的数据会在Redis重启后丢失。因此,为了保证数据不丢失,Redis实现了数据持久化的机制。这个机制会将内存中的数据存储到磁盘,重启后可以从磁盘中恢复。

Redis共有三种数据持久化的方式:

  • AOF日志:每执行一条写操作命令,就把该命令以追加的方式写到一个文件里;
  • RDB快照:将某一时刻的内存数据,以二进制的方式写入磁盘;
  • 混合持久化方式:Redis 4.0新增,集成了AOF和RBD的优点。

4.2 AOF 日志是如何实现的?

4.2.1 AOF 日志写入

Redis在执行完一条写操作命令后,就会把该命令以追加写的方式写到一个文件中。当Redis重启后,会读取该文件记录的命令,逐个执行来恢复数据。

请添加图片描述

为什么是先执行命令,然后再把命令写入日志?

Reids 是先执行写操作命令后,才将该命令记录到 AOF 日志里的,这么做其实有两个好处:

  • 避免额外的检查开销:如果先写入再执行,那在写入的时候还无法确定是否能够执行。需要增加一步检查命令。
  • 不会阻塞当前写操作命令的执行:因为是完成写操作再去写入之日。

也会存在风险:

  • 数据可能会丢失:如果完成了写操作但还没来得及写入日志,服务器宕机了,会丢失这个数据;
  • 可能阻塞其他操作:AOF日志也是在主线程中执行的,会阻塞后续的操作等待写入完成;
4.2.2 AOF 日志写回策略

Redis写入AOF日志的过程可以由下图所示:

  1. Redis执行完写操作命令后,会将命令追加到一个缓冲区;
  2. 然后通过write()系统调用,将该缓冲区的命令写入到磁盘中的AOF文件中。实际上这一步只会让命令拷贝到了AOF文件的内核缓冲区,什么时候写入到硬盘由内核决定

Redis提供了3种写回硬盘的策略,控制什么时候将数据写入硬盘

  • Always:每次写操作执行完成后,直接将AOF日志数据写回硬盘;
  • Everysec:写操作执行完成后,数据会先存放在AOF文件的内核缓冲区,每隔一秒将缓冲区的内容写回到磁盘。
  • No:Redis不控制写回的执行,完全交给操作系统来控制

在这里插入图片描述

4.2.3 AOF 重写机制

随着执行的写操作越来越多,AOF日志文件会越来越大,在数据恢复时会越慢,影响性能。因此,Redis提供了重写机制,来避免AOF日志文件越写越大

AOF重写机制是根据K-V数据中的键值对,将每个键值对形成一个命令,记录到「新的 AOF 文件」中,完成后用这个「新的 AOF 文件」替换掉原有的AOF文件。

在这里插入图片描述

AOF重写机制的本质就是**只保留最新的在使用重写机制后,就会读取 name 最新的 value(键值对) ,然后用一条 「set name xiaolincoding」命令记录到新的 AOF 文件,之前的第一个命令就没有必要记录了,因为它属于「历史」命令,没有作用了。这样一来,一个键值对在重写日志中只用一条命令就行了**。

AOF重写是怎么完成的?

Redis是在每次需要AOF重写时,通过**新开辟一个子进程bgrewriteaof来完成AOF重写 **。这是由于:

  • 不会阻塞主进程,主进程可以继续处理命令请求;
  • 如果是多线程,由于共享数据,需要通过锁机制来保证数据安全,会影响性能。而子进程是拷贝数据的副本,创建子进程时,父子进程是共享内存数据的,不过这个共享的内存只能以只读的方式,而当父子进程任意一方修改了该共享内存,就会发生**「写时复制」,于是父子进程就有了独立的数据副本**,就不用加锁来保证数据安全

数据不一致问题?

因为在重写过程中,主进程仍然可以正常处理命令。如果发生了对已有key-value的修改,由于**「写时复制」子进程中关于这个key-value和主进程中的数据出现了不一致。为了解决这个问题,Redis设置了一个AOF重写缓冲区**。

在重写AOF期间,主进程对于所有的写操作命令除了将其加入到**「AOF 缓冲区」,还会加入到「AOF重写缓冲区」。当子进程完成重写时,会向主进程发送一个信号**(进程间的通信方式),主进程收到信号时会执行:

  • 将**「AOF重写缓冲区」中的所有内容追加到「新的 AOF 文件」**中;
  • 用**「新的 AOF 文件」**覆盖掉「旧的 AOF 文件」

截止到此,就完成了整个AOF重写的工作。

4.3 RDB 快照是如何实现的?

Redis使用AOF进行恢复时,如果AOF日志较多,需要逐个执行,势必会使Redis的恢复缓慢。为了解决这个问题,Redis增加了RDB快照。

RDB快照就是记录某一个瞬间的内存数据(是数据而不是命令),由于是直接记录的数据,因此在恢复时不需要执行操作命令,只需要将RDB文件读入内存即可,效率很高

4.3.1 RDB快照生成方法

Redis提供了两个命令来生成RDB快照:savebgsave,它们的区别在于生成快照是否在「主进程」里执行

  • save命令:在主进程中生成RDB快照,如果写入时间太长,会导致主线程阻塞,影响性能;
  • bgsave命令:会创建一个**子进程来生成RDB快照**,避免主线程的阻塞。

Redis 的快照是全量快照,也就是说每次执行快照,都是把内存中的**「所有数据」都记录到磁盘中。所以执行快照是一个比较重的操作,如果频率太频繁,可能会对 Redis 性能产生影响。如果频率太低,服务器故障时,丢失的数据会更多。**

4.3.2 RDB快照如何保证数据一致性?

如果是使用bgsave命令来执行生成快照,此时主进程仍然可以继续处理操作,但是由于快照是在一瞬间的数据,所以不需要去关注是否数据发生了变化。因此,RDB快照不存在数据一致性问题

如果主线程执行写操作,则被修改的数据会复制一份副本,然后 bgsave 子进程会**把原来副本数据写入 RDB 文件(不去管新的),在这个过程中,主线程仍然可以直接修改原来的数据。因此,借助写时复制技术(Copy-On-Write, COW)**,RDB不用关注数据一致性问题。

4.3 为什么会有混合持久化?

😊 RDB 优点是数据恢复速度快,但是快照的频率不好把握。频率太低,丢失的数据就会比较多,频率太高,就会影响性能。

😊 AOF 优点是丢失数据少,但是数据恢复不快。

为了集成了两者的优点, Redis 4.0 提出了混合使用 AOF 日志和RDB快照,也叫混合持久化,既保证了 Redis 重启速度,又降低数据丢失风险。

混合持久化是如何实现的?

  • 使用了混合持久化,AOF 文件的前半部分是 RDB 格式的全量数据,后半部分是 AOF 格式的增量数据

    当开启了混合持久化,在AOF重写日志时,重写子进程就不是把数据转换成命令写入了,而是**直接生成当时数据库的RDB快照并写入到AOF文件中。然后,主进程中记录在AOF重写缓冲区的命令继续以AOF日志的格式写入到AOF日志文件中**,替换旧的的 AOF 文件。

在这里插入图片描述

混合持久化优点:

  • 混合持久化结合了 RDB 和 AOF 持久化的优点,开头为 RDB 的格式,使得 Redis 可以更快的启动,同时结合 AOF 的优点,有减低了大量数据丢失的风险

混合持久化缺点:

  • AOF 文件中添加了 RDB 格式的内容,使得 AOF 文件的可读性变得很差
  • 兼容性差,如果开启混合持久化,那么此混合持久化 AOF 文件,就不能用在 Redis 4.0 之前版本了

资料参考

内容大多参考自:图解Redis介绍 | 小林coding (xiaolincoding.com)

相关文章:

  • 北京网站建设多少钱?
  • 辽宁网页制作哪家好_网站建设
  • 高端品牌网站建设_汉中网站制作
  • android(安卓)最简单明了解释版本控制之MinSdkVersion、CompileSdkVersion、TargetSdkVersion
  • Python基础知识笔记——random模块
  • C++包管理之`vcpkg`简介
  • 如何限制 docker 使用cpu
  • HTML中a标签跳转后路径不正确?
  • IDEA 本地有jar包依赖文件,但是所有引用的jar包全部爆红
  • 【ROS 最简单教程 002/300】ROS 集成开发环境安装 (虚拟机版): Noetic
  • GLSL教程 第10章:高级渲染技术
  • QEMU 新增QMPHMP指令【原文阅读】
  • keil 启动在线调试后不能单步执行问题解决,卡在汇编代码
  • pyinstaller带浏览器一起打包playwright 独立运行exe
  • react子组件向父组件传参
  • R语言 爬取数据+简单清洗
  • 【前端学习笔记】CSS基础一
  • 2023河南萌新联赛第(二)场 南阳理工学院
  • 2017届校招提前批面试回顾
  • angular2 简述
  • Apache的80端口被占用以及访问时报错403
  • CSS相对定位
  • gcc介绍及安装
  • HTTP那些事
  • Linux编程学习笔记 | Linux多线程学习[2] - 线程的同步
  • 程序员该如何有效的找工作?
  • 每个JavaScript开发人员应阅读的书【1】 - JavaScript: The Good Parts
  • 日剧·日综资源集合(建议收藏)
  • 设计模式走一遍---观察者模式
  • 实战:基于Spring Boot快速开发RESTful风格API接口
  • 腾讯优测优分享 | 你是否体验过Android手机插入耳机后仍外放的尴尬?
  • 通过npm或yarn自动生成vue组件
  • 通过获取异步加载JS文件进度实现一个canvas环形loading图
  • 源码安装memcached和php memcache扩展
  • ​马来语翻译中文去哪比较好?
  • ​学习笔记——动态路由——IS-IS中间系统到中间系统(报文/TLV)​
  • ###C语言程序设计-----C语言学习(3)#
  • #ifdef 的技巧用法
  • #免费 苹果M系芯片Macbook电脑MacOS使用Bash脚本写入(读写)NTFS硬盘教程
  • $Django python中使用redis, django中使用(封装了),redis开启事务(管道)
  • $var=htmlencode(“‘);alert(‘2“); 的个人理解
  • %check_box% in rails :coditions={:has_many , :through}
  • ()、[]、{}、(())、[[]]等各种括号的使用
  • (175)FPGA门控时钟技术
  • (8)STL算法之替换
  • (二)WCF的Binding模型
  • (附源码)计算机毕业设计SSM疫情居家隔离服务系统
  • (六)库存超卖案例实战——使用mysql分布式锁解决“超卖”问题
  • (每日持续更新)jdk api之StringBufferInputStream基础、应用、实战
  • (十三)Java springcloud B2B2C o2o多用户商城 springcloud架构 - SSO单点登录之OAuth2.0 根据token获取用户信息(4)...
  • (一)使用IDEA创建Maven项目和Maven使用入门(配图详解)
  • (已解决)报错:Could not load the Qt platform plugin “xcb“
  • (转载)PyTorch代码规范最佳实践和样式指南
  • .L0CK3D来袭:如何保护您的数据免受致命攻击
  • .net 4.0 A potentially dangerous Request.Form value was detected from the client 的解决方案
  • .Net core 6.0 升8.0
  • .Net Core 生成管理员权限的应用程序
  • .NET WPF 抖动动画