Redis RDB和AOF持久化机制详解「建议收藏」

Redis RDB和AOF持久化机制详解「建议收藏」Redis支持RDB和AOF两种持久化机制,持久化功能有效的避免因进程退出造成的数据丢失问题,当下次重启时利用之前持久化文件即可实现数据恢复

「这是我参与11月更文挑战的第12天,活动详情查看:2021最后一次更文挑战」。

概念

Redis支持RDB和AOF两种持久化机制,持久化功能有效的避免因进程退出造成的数据丢失问题,当下次重启时利用之前持久化文件即可实现数据恢复

RDB

Redis提供RDB持久化功能,RDB持久化是把Redis 数在内存中的数据生成快照保存到硬盘的过程,触发RDB持久化过程分为手动触发和自动触发。

RDB持久化生成的RDB文件是一个经过压缩的二进制文件,通过这个文件可以还原生成RDB时数据库当时的完整数据,从而实现数据持久化,避免数据丢失。

RDB文件的创建和载入

RDB文件创建基本概念

有两个Redis命令可以用于生成RDB文件,一个是SAVE,另一个是BGSAVE。

SAVE命令会阻塞Redis服务进程,直到RDB文件创建完毕为止,在服务器进程阻塞期间,服务器不能处理任何命令请求。

image.png

当SAVE命令正在执行时,客户端发送的所有命令请求都会被拒绝,只有在服务器执行完SAVE命令,重新开始接受命令请求之后,客户端发送的命令才会被处理。

BGSAVE命令不会阻塞服务器进程,BGSAVE命令会派生出一个子进程,然后由子进程负责创建RDB文件,服务器进程继续处理命令请求,在BGSAVE命令执行期间,客户端发送的SAVE,BGSAVE命令都会被拒绝。

image.png

创建RDB文件实际是由rdbsave函数来完成,save和bgsave命令会以不同的方式调用这个函数。

文件载入

RDB文件载入是在服务器启动时自动执行的,只要Redis服务器在启动时检测到RDB文件存在,就会自动载入到RDB文件。我们来看下Redis启动时打印的日志文件

image.png

DB loaded from disk 就是服务器在成功载入RDB文件之后打印的。

这里要强调一下,因为AOF文件更新频率通常比RDB文件更新频率高,所以如果服务器开启了AOF持久化功能,那么服务器会优先使用AOF文件来还原数据,只有在AOF关闭时,才会使用RDB文件来还原数据。

载入RDB文件实际是由rdbload函数来完成。

服务器在载入RDB文件期间,会一直处于阻塞状态,直到载入工作完成。

自动保存

因为BGSAVE命令不会阻塞主服务器进程,所以Redis允许用户通过设置服务器配置的save选项,让服务器自动每隔一段时间执行一次BGSAVE命令。

image.png

  • 服务器在900秒之内对数据库进行了至少一次修改。

  • 服务器在300秒之内对数据库进行了至少10次修改。

  • 服务器在60秒之内,对数据库进行了至少10000次修改。

只要满足这三个条件的任意一个,BGSAVE命令就会被执行。

如果用户没有主动设置save选项,服务器就会为save选项设置默认条件,上图展示的就是默认条件。

自动保存

服务器会根据save选项设置的保存条件,设置服务器状态redisServer结构的saveparams属性

image.png

saveparams属性是一个数组,数组中的每个元素都是一个saveparam结构,每个saveparam结构都保存了一个save选项设置的保存条件。

image.png

除了saveparams数组之外,服务器状态还维持着一个dirty计数器和一个lastsave属性。

dirty计数器用来记录距离上一次成功执行SAVE命令或者BGSAVE命令之后,服务器对数据库状态进行了多少次修改。

lastsave属性是一个UNIX时间撮,记录了服务器上一次成功执行SAVE命令或者BGSAVE命令的时间。

服务器每成功执行一次数据库修改命令,dirty计数器会进行更新,修改多少次数据库dirty值就会增加多少。

Redis的服务器周期性操作函数serveCron默认每隔100毫秒执行一次,会检查save选项设置的保存条件是否已经满足,如果满足,就执行BGSAVE命令。

RDB文件结构

image.png

RDB文件基本上就是由这五个部分组成。

  • REDIS:RDB文件开头是REDIS部分,保存着”REDIS”五个字符。通过这5个字符,程序在载入文件时,可以快速检查所载入的文件是否是RDB文件。

  • db_vsersion长度是4字节,它的值是一个字符串表示的整数。记录了RDB文件到版本号。

  • databases:包含着零个或多个数据库,以及各个数据库中的键值对数据。

  • EOF常量的长度为1字节,这个常量标志着RDB文件正文内容的结束,当程序读入这个值,就代表所有键值对数据已经加载完毕。

  • check_sum是一个8字节长的整数,保存着一个校验和,这个校验和是程序通过对REDIS,db_version,databases、EOF四个部分的内容进行计算得出的。服务器载入RDB文件时会将载入数据时计算的校验和与check_sum进行对比,来检查RDB文件是否有出错。

image.png

databases部分

这里重点说下databases部分,如果服务器的0号数据库和3号数据库非空,那么服务器将创建一个下图所示的RDB文件

image.png

每个非空的数据库都是由SELECTDB、db_number、key_value_pairs三个部分组成

image.png

  • SELECTDB:长度为1字节,当程序遇到这个值,就知道接下来要读入的将是一个数据库号码

  • db_number:保存着一个数据库号码,当程序读入这个db_number,服务器会调用SELECT命令,根据读入的数据库号码进行数据库切换,使得之后读入的键值对可以载入到正确的数据库中。

  • key_value_pairs:保存了数据库的所有键值对数据,如果键值对带有过期时间,这个过期时间也会和键值对保存在一起。

不带过期时间的键值对在RDB文件中由TYPE、key、value三部分组成

带过期时间的键值对由EXPIRETIME_MS,ms,type,key,value组成。

type记录了value的类型,EXPIRETIME_MS是个常量,1字节,它告知程序接下来要读入的是一个以毫秒为单位的过期时间。

ms是一个8字节长的带符号整数记录了一个亿毫秒为单位的时间戳。

回顾

image.png

AOF

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

AOF持久化实现

命令追加

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

写入与同步

Redis的服务器进程是一个事件循环,在服务器每次结束一个事件循环之前,它都会调用flushAppendOnlyFile函数,考虑是否需要将aof_buf缓冲区的内容写入和保存到AOF文件里面。

flushAppendOnlyFile函数的行为由服务器配置的appendfsync选项的值来决定

image.png

always:命令写入aof_buf后调用系统fsync操作同步到AOF文件,fsync完成后线程返回  

everysec:命令写入aof_buf后调用系统write操作,write完成后线程返回。fsync同步文件操作由专门线程每秒调用一次  

no:命令写入aof_buf后调用系统write操作,不对AOF文件做fsync同步,同步硬盘操作由操作系统负责,通常同步周期最长30s  

配置为always时,每次写入都要同步AOF文件,在一般的SATA硬盘上,Redis只能支持大约几百TPS写入,显然跟Redis高性能特性背道而驰,不建议配置。  

配置为no,由于操作系统每次同步AOF文件的周期不可控,而且会加大每次同步硬盘的数据量,虽然提升了性能,但数据安全性无法保证。   

配置为everysec,是建议的同步策略,也是默认配置,做到兼顾性能和数据安全性。理论上只有在系统突然宕机的情况下丢失1秒的数据。

重写

随着命令不断写入,会导致aof文件越来越大,文件体积会越来越大,体积过大的AOF文件很可能对Redis服务器甚至整个计算机造成影响,为了解决这个问题,Redis提供了AOF文件重写功能,通过该功能,Redis服务器会创建一个新的AOF文件来替代现有AOF文件,新的AOF文件不会包含任何浪费空间的冗余命令,所以新的AOF文件体积会比旧AOF文件体积要小的多。

重写具体实现

AOF文件重写不需要对现有AOF文件进行任何读取,分析或者写入操作,这个功能是通过读取服务器的数据库内容来实现,考虑以下情景

image.png

为了记录animals键值,AOF文件必须保存上面列出的四条命令。

而当AOF文件重写时,服务器会直接通过读取当前animals键的值,生成一条sadd animals “Dog” “Panda” “Tiger” “Lion” “Cat” 命令来代替上面的四条命令,这样就将保存animals键所需命令从四条减少到一条了。

AOF后台重写

AOF重写会进行大量写入操作,所以为了避免因为重写造成服务器被阻塞,Redis服务器会使用子进程来进行执行,子进程进行AOF重写期间,服务器进程可以继续处理命令请求。

使用子进程也会存在一个问题,因为子进程重写期间,服务器进程会继续处理命令请求,新的命令会对现有数据库内容进行修改,从而造成当前数据库内容和重写后的AOF文件内容不一致。

为了解决这个问题,Redis服务器设置了AOF重写缓冲区,这个缓冲区在服务器创建子进程之后开始使用,当Redis服务器执行完一个写命令后,它会同时将这个写命令发送给AOF缓冲区和AOF重写缓冲区。

从创建为AOF重写的子进程开始,服务器执行的所有写命令都会被记录到AOF重写缓冲区中。

当子进程完成AOF重写之后,会向服务器进程发送一个信号,服务器进程接收到这个信号会做两件事

  • 将AOF重写缓冲区的所有内容写入到新的AOF文件

  • 将新的AOF文件进行改名,原子性的覆盖旧的AOF文件

image.png

回顾

image.png

RDB和AOF对比

image.png

  • RDB文件的载入工作是在服务器启动时自动执行的,并没有专门的命令。但是由于AOF的优先级更高,因此当AOF开启时,Redis会优先载入AOF文件来恢复数据;只有当AOF关闭时,才会在Redis服务器启动时检测RDB文件,并自动载入。服务器载入RDB文件期间处于阻塞状态,直到载入完成为止。

事务

事务主要的几个命令

  1. multi

事务命令执行的开始,当执行这个命令后,接下来所有的redis命令会存入一个队列当中,不会立即执行,只有当执行exec后,所有的命令会按照进入队列的命令先后执行

  1. exec

事务命令的结束,当执行这个命令时,会把先前进入队列的命令一一执行

3.watch

watch 命令是给键加监控,如果在当前事务中,该键发送了更改,则最终就不会去执行。会返回空

4.DISCARD

清除所有先前在事务中的命令

  1. unwatch

清除所有先前监控的键

示例

image.png

image.png

watch命令原理

带有watch命令的事务会将客户端和被监控的键在数据库中的watched_keys字典中进行管理,当键被修改时,程序会将所有监视被修改键的客户端的redis_dirty_cas 标志打开。

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 举报,一经查实,本站将立刻删除。
转载请注明出处: https://daima100.com/13055.html

(0)

相关推荐

  • oracle nvl函数不起作用_oracle nvl函数用法

    oracle nvl函数不起作用_oracle nvl函数用法Oracle的NVL函数用法 从两个表达式返回一个非 null 值。语法NVL(eExpression1, eExpression2)参数eExpression1, eExpression2如果 e…

    2023-04-09
    157
  • Mac m1 配置java环境

    Mac m1 配置java环境mac for m1芯片,安装java工具,配置java环境变量,使用idea测试java环境是否配置成功。

    2023-11-11
    137
  • 如何退出vim

    如何退出vim在软件开发中,经常会用到vim这款文本编辑器。然而,对于初学者来说,vim的操作不免会有些困难,尤其是退出vim这一步更是令人头疼。因此,本文将针对如何退出vim这一问题进行阐述,帮助读者更好地理解vim的使用方法。

    2024-05-20
    68
  • 石家庄商业银行是河北银行吗_河北银行资产规模

    石家庄商业银行是河北银行吗_河北银行资产规模11 月 1 日,秦皇岛银行新一代分布式核心系统成功投产并稳定安全运行超过三个月,标志着秦皇岛银行数字化转型应用和服务水平登上了一个新台阶。 这是秦皇岛银行有史以来规模最大、范围最广、难度最高的一次系

    2023-06-13
    147
  • Mysql基础01-语法

    Mysql基础01-语法数据库 数据的存储:将数据放到表中,表再放到库中。 一个数据库中可以有多个表,每个表都有一个名字,用来标识自己。表名具有唯一性。 表由列组成,我们也称为字段。每个字段描述了它所含有的数据的意义表由列组

    2022-12-26
    148
  • cnc加工中心编程代码_加工中心m代码大全

    cnc加工中心编程代码_加工中心m代码大全有些烦恼是我们凭空虚构的,而我们却把它当成真实去承受。想得太多只会毁了你,让你陷入忐忑,让实际上本不糟糕的事情,变得糟糕。

    2022-12-14
    251
  • Python Obj Age: 优化程序性能的关键

    Python Obj Age: 优化程序性能的关键Python是一种非常流行的编程语言,因为它易学易用,是一种高级语言,同时也是一种解释型语言。Python Object的Age是优化Python代码的关键,它是程序的重要组成部分,影响程序代码的性能。

    2024-03-08
    81
  • 记录数据库连接数_access怎么连接数据库

    记录数据库连接数_access怎么连接数据库 由于隔了很长时间去使用C#时,总是忘记与数据库的连接,这里做个简单的总结(以与Sqlite数据库连接为例); 下载数据库地址(官方地址),按照自己的系统版本下载; https://www.s…

    2023-03-24
    146

发表回复

您的电子邮箱地址不会被公开。 必填项已用*标注