IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> 大数据 -> Redis的持久化策略 -> 正文阅读

[大数据]Redis的持久化策略

Redis持久化

??Redis有一个很特殊的地方是Redis是一个内存数据库,为了能够实现数据的永久化,Redis提供了两种永久化的方式来解决这个问题。

RDB持久化

??RDB持久化功能所生成的RDB文件是一个经过压缩的二进制文件,通过该文件可以还原生成RDB文件时的数据库状态。
在这里插入图片描述
??因为RDB文件是存储在硬盘中的,所以即使Redis服务器进程退出,甚至运行Redis服务器的计算机停机,但只要RDB文件依然存在,Redis服务器就可以用它来还原数据库状态。

RDB文件的创建与载入

??Redis中提供了两个命令用于生成RDB文件,一个是SAVE,另一个是BGSAVE。它们之间的区别在于:

  • SVAE命令会阻塞Redis服务器进程,直到RDB文件创建完毕为止,在服务器进程阻塞期间,服务器不能处理任何命令请求;
  • BGSAVE命令则会派生出一个子进程,然后由子进程负责创建RDB文件,服务器进程(父进程)继续处理命令请求。

??和创建RDB文件不同,RDB文件的载入工作是在服务器启动时自动执行的,所以Redis并没有专门用于载入RDB文件的命令,只要Redis服务器在启动时检测到RDB文件存在,它就会自动载入RDB文件。
??注: 因为AOF持久化策略更新频率高于RDB方式,所以在服务器开启了AOF持久化功能时,会优先使用AOF文件来还原数据库状态。

自动间隔性保存

??因为BGSAVE命令可以在不阻塞服务器进程的情况下进行,所以Redis允许用户通过设置服务器配置的save选项,让服务器每隔一段时间自动执行一次BGSAVE命令。
在这里插入图片描述
??假如我们向服务器提供这样的配置,那么只要满足三个条件中的任意一个,BGSAVE命令就会被执行。

设置保存条件

??服务器会根据save选项所设置的保存条件,设置服务器状态RedisServer结构的saveparams属性,它是一个数组,每个saveparam结构都保存了一个save选项设置的保存条件:
在这里插入图片描述

dirty计数器和lastsave属性

??服务器通过dirty计数器来记录距离上一次成功执行SAVE命令或者BGSAVE命令之后,服务器对数据库进行了多少次修改。
??lastsave属性是一个UNIX时间戳,记录了服务器上一次成功执行SVAE命令或者BGSAVE命令的时间。

检查保存条件是否满足

??Redis的服务器周期性操作函数serverCron默认每隔100毫秒就会执行一次,该函数用于对正在运行的服务器进行维护,它的其中一项工作就是用来检查save选项设置的保存条件是否已经满足,如果满足的话就执行BGSAVE命令。
??简单来说就是通过serverCron函数对dirty计数器和lastsave时间戳与saveparams数组中记录的条件进行比较,如果满足数组中记录的条件,那么就通过BGSAVE命令来进行一次持久化操作。

RDB文件结构

在这里插入图片描述
??RDB文件的最开头是REDIS部分,这个部分的长度为5字节,保存着“REDIS”五个字符。这无个字符的作用是在文件载入的时候快速检查所载入的文件是否是RDB文件。
??db_version长度为4字节,它的值是一个字符串表示的整数,这个整数记录了RDB文件的版本号。
??databases部分包含着零个或者任意多个数据库,以及各个数据库中的键值对数据。如果服务器的所有数据库都是空的,那么这个部分也是空的,长度为0字节,如果服务器的数据库不为空,那么这个部分也不为空,根据数据库内容的不同,这部分的长度也不为空。
??EOF常量的长度为1字节,这个常量标志着RDB文件正文内容的结束,当读入程序遇到这个值的时候,它知道所有数据库的所有键值对都已经载入完毕了。
??check_sum是一个8字节的无符号整数,保存着一个检验和,这个数字是通过对REDIS、db_version、databases、EOF四个部分的内容进行计算得出的。服务器在载入RDB文件时,会将载入数据所计算出的校验和与这个数字进行比较,以此来检查RDB文件是否有出错或者损坏的情况出现。
databases部分
??一个RDB文件的databases部分可以保存任意多个非空数据库。例如,服务器的0号数据库和3号数据库非空,那么服务器将创建一个如图所示的RDB文件。
在这里插入图片描述
??每个非空数据库在RDB文件中都可以保存为SELECTDB、db_number、key_value_pairs三个部分。
在这里插入图片描述
??SELECTDB常量的长度为1字节,当读入程序遇到这个值的时候,它知道接下来要读入的将是一个数据库号码。
??db_number保存着一个数据库号码,根据号码的不同,这个部分的长度可以是1字节、2字节或者5字节。当程序读入db_bumber部分之后,服务器会调用SELECT命令,根据读入的号码进行数据库切换,使得之后读入的数据可以载入到正确的数据库中。
??key_value_pairs部分保存了数据库中的所有键值对数据,如果键值对带有过期时间,那么也会和键值对保存在一起。

AOF持久化

??RDB持久化是通过保存数据库中的键值对来记录数据库状态,AOF持久化是通过保存Redis服务器所执行的写命令来记录数据库状态的。

AOF持久化的实现

??AOF持久化功能的实现可以分为命令追加、文件写入、文件同步三个步骤。

命令追加

??当AOF持久化功能处于打开状态时,服务器在执行完一个写命令之后,会以协议格式将被执行的写命令追加到服务器状态的aof_buf缓冲区的末尾。

AOF文件的写入与同步

??Redis的服务器进程就是一个事件循环,这个循环中的文件事件负责接手客户端的命令请求,以及向客户端发送命令回复,而事件事件则负责执行像serverCron函数这样需要定时运行的函数。因为服务器在处理文件事件时可能会执行写命令,使得一些内容被追加到aof_buf缓冲区里面,所以在服务器每次结束一个事件循环之前,它都会调用flushAppendOnlyFile函数,考虑是否需要将aof_buf缓冲区的内容写入和保存到AOF文件里面。
不同appendfsync值产生不同的持久化行为
??如果用户没有主动为appendfsync选项设置值,那么appendfsync选项的默认值为everysec。
??通过安全性和效率的角度来分析,当值为always时,效率是最慢的,但是从安全性来说,always也是最安全的,即使出现问题,也只是丢失一个事件循环中产生的命令数据。当值为everysec时,从效率上来说,everysec模式足够快,当出现故障时会丢失掉一秒钟的命令数据。当值为no时,服务器在每个事件循环中都要将aof_buf缓冲区中的所有内容写入到AOF文件,至于何时进行文件同步,则由操作系统控制。

AOF文件的载入与数据还原

??因为AOF文件里面包含了重建数据库状态所需的所有写命令,所以服务器只要读入并重新执行一遍AOF文件里边保存的写命令,就可以还原服务器关闭之前的数据库状态。详细步骤如下:

  • 创建一个不带网络连接的伪客户端:因为Redis的命令只能在客户端上下文中执行,而载入AOF文件时所使用的命令直接来源于AOF文件而不是网络连接,所以服务器使用了一个没有网络连接的伪客户端来执行AOF文件保存的写命令,伪客户端执行命令的效果和带网络连接的客户端执行命令的效果完全一样。
  • 从AOF文件中分析并读取出一条写命令。
  • 使用伪客户端执行被读取出的命令。
  • 一直执行步骤二和步骤三,知道AOF文件中所有的写命令都被处理完毕为止。

AOF重写

??AOF持久化是通过保存被执行的命令来记录数据库状态的,所以生成的文件会随着使用变得越来越大对后续的使用造成影响。所以我们需要通过对AOF文件的重写来缩小文件的大小。

AOF文件重写的实现

??虽然将缩小文件大小的过程叫做文件的重写,但是在重写的过程中并不需要对现有的AOF文件进行任何读取、分析或者写入操作,这个功能是通过读取服务器当前的数据库状态来实现的,即首先从数据库中读取键现在的值,然后用一条命令去记录键值对,代替之前记录这个键值对的多条命令,这就是AOF重写功能实现的原理。

AOF后台重写

??因为直接在主进程中进行重写操作的话服务器在这个期间无法处理客户端发来的命令请求,所以Redis将AOF重写程序放到子进程里执行,这样可以同时达到两个目的:

  • 子进程进行AOF重写期间,服务器进程可以继续处理命令请求。
  • 子进程带有服务器进程的副本,使用子进程而不是线程,可以在避免使用锁的情况下,保证数据的安全性。

??当时在这种情况下,子进程在进行文件重写时,服务器进程还需要继续处理命令请求,而新的命令可能会对现有的数据库状态进行修改,从而使得服务器当前的数据库状态和重写之后AOF文件所保存的数据库状态不一致。
??为了解决这个问题,Redis服务器设置了一个AOF重写缓冲区,这个缓冲区在服务器创建子进程之后开始使用,当Redis服务器执行完一个写命令之后,它会同时将这个写命令发送给AOF缓冲区和AOF重写缓冲区。也就是说在重写期间,服务器进程需要执行以下三个操作:

  • 执行客户端发来的命令
  • 将执行后的写命令追加到AOF缓冲区
  • 将执行后的写命令追加到AOF重写缓冲区
    在这里插入图片描述
    ??这样可以保证:
  • AOF缓冲区的内容会定期被写入和同步到AOF文件中,对现有AOF文件的处理工作会正常进行。
  • 从创建子进程开始,服务器执行的所有写命令都会被记录到AOF重写缓冲区里面。
    ??当子进程完成重写工作之后,会向主进程发送一个信号,父进程在收到该信号之后,会调用一个信号处理函数,并进行下列操作:
  • 将AOF重写缓冲区的所有内容写入到新AOF文件中,此时新AOF文件所保存的数据库状态将和服务器当前的数据库状态一致。
  • 对新的AOF文件进行改名,原子地覆盖现有AOF文件,完成新旧两个AOF文件的替换。
    ??当信号处理函数执行完毕后,父进程就可以像往常一样接受命令请求。这就是BGREWRITEAOF实现的原理。
  大数据 最新文章
实现Kafka至少消费一次
亚马逊云科技:还在苦于ETL?Zero ETL的时代
初探MapReduce
【SpringBoot框架篇】32.基于注解+redis实现
Elasticsearch:如何减少 Elasticsearch 集
Go redis操作
Redis面试题
专题五 Redis高并发场景
基于GBase8s和Calcite的多数据源查询
Redis——底层数据结构原理
上一篇文章      下一篇文章      查看所有文章
加:2021-12-08 13:53:00  更:2021-12-08 13:54:56 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年11日历 -2024/11/24 9:31:33-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码