Redis(二)RDB AOF持久化

Redis的持久化通过RDB和AOF两种方式确保数据安全。RDB在特定时间点生成数据库快照,适合灾难恢复;AOF记录每次写操作,保证数据不丢失。AOF重写优化文件体积,子进程执行避免阻塞主线程。同步策略(always、everysec、no)影响数据安全性与性能。
摘要由CSDN通过智能技术生成

因为Redis是内存数据库,它将自己的数据库状态储存在内存里面,所以如果不想办法将储存在内存中的数据库状态保存到磁盘里面,那么一旦服务器进程退出,服务器中的数据库状态也会消失不见。为了解决这个问题,Redis提供了RDB持久化AOF持久化

RDB持久化

RDB持久化既可以手动执行,也可以根据服务器配置选项定期执行,该功能可以将某个时间点上的数据库状态保存到一个RDB文件中。RDB持久化功能所生成的RDB文件是一个经过压缩的二进制文件,通过该文件可以还原生成RDB文件时的数据库状态。
在这里插入图片描述

RDB文件的载入

在这里插入图片描述
注意:因为AOF文件的更新频率通常比RDB文件的更新频率高:所以

  1. 如果服务器开启了AOF持久化功能,那么服务器会优先使用AOF文件来还原数据库状态
  2. 只有在AOF持久化功能处于关闭状态时,服务器才会使用RDB文件来还原数据库状态

RDB文件的保存

save

在这里插入图片描述
当执行save命令执行时,Redis服务器会被阻塞,所以当SAVE命令正在执行时,客户端发送的命令请求都会被拒绝。只有在服务器执行完save命令,重新开始接收命令请求之后,客户端发送的命令才会被处理。

bgsave (background save)

在这里插入图片描述
因为BGSAVE命令的保存工作是由子进程执行的,所以在子进程创建RDB文件的过程中,Redis服务器仍然可以继续处理客户端的命令请求,但是,在BGSAVE命令执行期间,服务器处理SAVE、BGSAVE、BGREWRITEAOF 三个命令的方式会和平时有所不同。

  • 在BGSAVE命令执行期间,客户端发送的SAVE命令会被服务器拒绝,服务器禁止SAVE命令(BGSAVE 命令)和BGSAVE命令同时执行是为了避免父进程(服务器进程)和子进程同时执行。
  • 如果BGSAVE命令正在执行,那么客户端发送的BGREWEITEAOF命令会被延迟等到BGSAVE命令执行完毕之后执行。
  • 如果BGREWRITEAOF命令正在执行,那么客户端发送的BGSAVE命令会被服务器拒绝。

自动间隔性保存

因为SAVE会阻塞服务器,而BGSAVE则不会。Redis允许用户设置服务器配置的save选项,让服务器每隔一段时间自动执行一次BGSAVE命令
在这里插入图片描述
只要满意以下三个条件中的任意一个,BGSAVE命令就会被执行:

  1. 服务器在900秒之内,对数据库进行了至少1次修改
  2. 服务器在300秒之内,对数据库进行至少10次修改
  3. 服务器在60秒之内,对数据库进行了至少10000次修改

对应 redisServer结构

在这里插入图片描述
dirty:计数器记录距离上一次成功执行SAVE命令或者BGSAVE之后,服务器掉数据库状态(服务器中的所有数据库)进行了多少次修改(包括写入、删除、更新等操作)
lastsave:属性是一个UNIX时间戳,记录了服务器上一次成功执行SAVE命令或者BGSAVE命令的时间

检查保存条件是否满足

Redis的服务器周期性操作函数serverCron默认每个100毫秒就会执行一次,该函数用于对正在运行的服务器进行维护,他的其中一项工作就是检查save选项设置的保存条件是否已经满足,如果满足的话,就执行BGSAVE命令。该函数会判断 当中的时间(UNIX时间戳) 减去 lastsave时间 和 dirty次数 是否满足 saveparams数组当中任何一个条件,如果满足执行bgsave。。执行完毕后重置 dirty 和 lastsave的数据
在这里插入图片描述

AOF持久化

在这里插入图片描述

在 redisServer结构当中存在一个AOF缓冲区,当我们开启AOF持久化时候,客户端每输入一条指令都会被保存在AOF缓冲区当中
在这里插入图片描述

AOF文件的写入与同步

跟执行BGSAVE的serverCron一样,执行AOF的写入同样需要一个事件循环。执行把AOF缓冲中的数据写入到AOF文件里面。一下介绍一下不一样的同步机制
在这里插入图片描述

appendfsync选项的值同步文件的行为
always将AOF缓冲区的所有内容写入并同步到AOF文件
erverysec将AOF缓冲区中的所有内容写入到AOF文件,如果上次同步AOF文件的时间距离现在超过一秒钟,那么再次对AOF文件进行同步,并且这个同步操作是由一个线程专门负责执行的
no将AOF缓冲区中的所有内容写入到AOF文件,但并不对AOF文件进行同步,何时同步由操作系统来决定

有没有发现一个很奇怪的问题,写入AOF文件,怎么还要需要同步操作。不是已经同步了吗? always和no 到底有什么区别?接下来我们讲讲 文件的写入和同步

为了提升文件的写入效率,在现代操作系统中,当用户调用内核函数write,将一些数据写入到文件的时候,操作系统通常会将写入的数据暂时保存在一个内存缓冲区当中,等缓冲区的空间被填满了、或者超过了指定的时限之后,才真正地将缓冲区中的数据写入到磁盘里面。 这种做法虽然提高了效率,但也为了写入数据带来了安全问题,因为如果计算机发生停机,那么保存在内存缓冲区里面的写入数据将会丢失。为此,系统提供了fsync和fdatasync两个同步函数,它们可以强制让系统立即将缓冲区中的数据写入到硬盘里面,从而保证写入数据的安全性,也就对应了 always这个选项

AOF文件的载入与数据还原

在这里插入图片描述
我们知道redis默认有16个库,所以执行命令需要知道是对于哪一个库执行命令。AOF文件里面肯定做了区别。保证对应的命令执行在对应的数据库当中。

AOF重写

如果AOF不断的追加,将会是无穷无尽的结果。set A a ,后 del A 这种语句,还有很多数据改来改去的命令。都有可能导致AOF在读取执行命令时候,做无用功。为此Redis提供了一项功能AOF重写。创建一个新的AOF文件来替换现有的AOF文件,新旧两个AOF文件所保存的数据库状态相同,但新的AOF文件不会包含任何浪费空间的沉余命令,所以以新AOF文件的体积会比旧AOD文件的体积要小很多。

AOF重写的实现***重点

因为AOF重写需要执行大量的读写操作,存在大量的IO操作,所以调用这个函数的线程将被长时间阻塞,因为Redis服务器使用单个线程来处理命令的请求,所以如果由服务器直接调用GBREWRITEAOF函数,那么在重写AOF文件期间,服务器将无法处理客户端发来的命令请求。因此Redis决定将AOF重写程序放到子进程里面执行,有两个目的

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

进程与子进程

AOF重写过程

在这里插入图片描述
因为子进程不会阻塞到父进程的运行,在子进程执行重写任务的时候,因为CPU调度的原因,父进程也可以执行。因此这时候父进程还是可以接收到客户端发送的指令。为此Redis在 执行AOF文件重写的时候设置使用一个 AOF重写缓冲区。在有子进程执行重写的时候,启动该 AOF重写缓冲区。当服务器接收到指令的时候,同时向AOF缓冲区 ,AOF重写缓冲区写入数据。流程如下图

时间服务器进程(父进程)子进程
T1执行命令 SET K1 V1$1600
T2执行命令 SET K2 V2$1600
T3执行命令 SET K3 V3$1600
T4创建子进程,执行AOF文件的重写(开始使用 AOF重写缓冲区)开始执行AOF重写
T5执行命令 SET K4 V4执行重写操作
T6执行命令 SET K5 V5执行重写操作
T7执行命令 SET K6 V6完成AOF文件的重写,向父进程发送信号
T8接收到子进程发送的信号,将AOF重写缓冲区的内存,追加的新的AOF文件当中
T9用新的AOF文件覆盖旧的AOF文件

T9 将会一个原子操作,保证新旧两个AOF文件的替换

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值