Redis(1)——持久化

目录

一、RDB

[1.1 RDB的触发方式](#1.1 RDB的触发方式)

[1.2 bgsave的流程](#1.2 bgsave的流程)

[1.3 实际执行](#1.3 实际执行)

[1.4 RDB的优缺点](#1.4 RDB的优缺点)

二、AOF

[2.1 开启AOF](#2.1 开启AOF)

[2.2 AOF文件写入](#2.2 AOF文件写入)

[2.3 AOF重写机制](#2.3 AOF重写机制)

[2.4 AOF重写的流程](#2.4 AOF重写的流程)

[2.5 混合持久化](#2.5 混合持久化)

[2.6 数据恢复](#2.6 数据恢复)


Redis的直观的特性就是相比数据库更快,效率更高,这是因为Redis的数据存储在内存上,所以我们可以做到快速读写,但是如果数据值存放到内存上是不持久的,如果主机或进程重启,数据就不存在了。

所以我们Redis的数据既要存储在内存上以此来实现"快",同时也要存储到硬盘上,以此来实现持久化。这样如果Redis重启后也可以从硬盘中读取数据来恢复内存中的数据

那么Redis该如何把数据存储到硬盘上呢,Redis向我们提供了两种策略

RDB:Redis DataBase :定期备份

AOF:Append Only File:实时备份

一、RDB

RDB定期把我们Redis内存中的数据,都写入到硬盘中,生成一个"快照"。可以理解为Redis给内存当前存储的数据赶紧拍个照片生成一个文件,存储到硬盘中,后续如果Redis重启,就可以通过硬盘里的"快照"文件恢复内存的数据

1.1 RDB的触发方式

1. 手动触发

我们可以通过在Redis命令行中输入指定命令来触发快照的生成

  • save :执行save的时候,Redis就会把让所有资源都用来进行"快照生成"操作,此时就会阻塞Redis的其他命令,所以我们一般不建议使用save命令
  • bgsave :bg就是background的意思,所以这个"快照生成"的过程是在背后进行的,不会阻塞Redis,也就不会影响Redis处理别的命令

2. 自动触发

除了在Redis客户端命令行输入指令的方式,我们还可以在Redis的配置文件中进行配置,让Redis在一定时间内自动进行RDB

在etc/redis文件夹中有一个redis.conf配置文件

文件中这里的配置就是对RDB的自动触发配置

3600 1:在3600秒(1小时)至少有1次数据修改

300 100:在300秒(5分钟)至少有100次数据修改

60 10000:在60秒(1分钟)至少有10000次数据修改

如果觉得这个配置不符合我们的业务需求,也可以在这个配置文件中进行修改

同时我们可以在这个配置文件中查看快照文件的位置

我们进入快照文件查看,这个rdb文件是一个二进制文件,内存中的数据以二进制的形式保存到这个文件中,redis重启的时候就会去读取这个文件,从而恢复内存中的数据,如果我们对这个文件进行了修改,redis服务可能就无法启动了

1.2 bgsave的流程

  • 当我们触发bgsave命令时,父进程首先会判断当前是否有其他正在执行的子进程,如果存在bgsave直接返回,不做任何操作
  • 如果没有其他子进程,父进程调用fork(),就会创建一个子进程,这个子进程会拥有父进程的所有信息,可以说父进程和子进程是相同的,子进程的物理内存是通过写时复制机制和父进程共享
    • 写时复制:如果是读操作的命令,子进程仍然和父进程共享内存空间,但是如果客户端输入写操作的命令,父进程就会申请一块新的空间,在这个新的空间进行修改。
    • 比如:父进程有个变量n=10,调用fork(),子进程也会有一个变量n=10,并且和父进程的n变量共享一块内存空间,父进程还要继续相应客户端的命令,如果客户端输入了写操作的命令,修改n=20,此时父进程就会申请一块新空间存储n=20,子进程的n还是等于10,并且跟父进程也不是共享一块空间了
    • 根据结果来说,就是子进程只会拥有fork()调用之前的所有数据。
  • fork()调用之后,子进程遍历当前内存所有的数据,按照RDB文件的格式,将数据写入一个临时文件
  • 写入完成之后,再把这个文件重命名为dump.rdb,替换原来旧的RDB快照文件

1.3 实际执行

先查看dump.rdb详情信息,inode是800816,文件内部的信息如下

我们现在一个客户端上设置三个键值对,此时我们去另一个客户端查看一下快照文件

可以看到dump.rdb的详情信息,他的inode此时是802428,和之前相同,可见并没有把我们直接设置的键值对储存起来,这是因为我们还没有满足自动触发rdb的条件

此时我们手动触发rdb

再去查看一下快照文件的信息,发现inode已经和之前不同了,说明确实进行了快照文件的替换

我们进入文件查看,发现里面确实存储了我们之前设置的键值对

我们再设置一个key4键值对

设置完后我们进入rdb快照文件,里面仍只有三个键值对,并没有我们刚刚设置的key4

此时我们退出客户端,重新启动redis服务,再进入客户端,发现key4竟然还是保存的

我们再进入rdb文件,发现key4保存在文件中了

说明,自动触发rdb快照除了配置redis.conf文件,在重新启动服务器的时候,redis也会自动触发rdb机制,保存快照文件

上述重启redis服务器的方式是正常关闭服务器的方式,我们再试一下非正常关闭服务器

先设置键值对key5

然后进行查看redis服务的进程号

直接使用kill -9命令删除进程,这样属于非正常关闭,我们再进入redis客户端,发现key5并没有存储成功

1.4 RDB的优缺点

优点

  • RDB是一个二进制文件,代表Redis在某个时间点上数据快照,非常适用于备份等场景
  • Redis加载RDB恢复数据远远快于AOF的方式

缺点

  • RDB存储数据没有办法做到实时持久化,上述提到的自动触发RDB也是有时间限制的,满足一段时间内固定次数修改才会触发RDB,那么如果还未触发之前服务器就挂了,这段时间内我们的数据就丢失了
  • RDB文件使用特定二进制格式保存,Redis版本演进过程中有多个RDB版本,兼容性会有风险

二、AOF

AOF持久化是以独立日志的方式记录每次写命令,AOF文件是文本文件,重启时再重新执行AOF文件的命令达到恢复数据的目的。相比于RDB一段时间记录数据,AOF解决了数据持久化的实时性,目前已经是Redis持久化的主流方式。如果将RDB比作是照片,记录了十点和十一点两张照片,那么AOF就是摄影,拍摄了十点到十一点一个小时的内容,所以保证了实时性

2.1 开启AOF

同样要在redis.conf里配置,这里默认是no未开启,我们把no改成yes,此时就开启AOF

AOF的日志命名是"appendonly.aof",和之前的dump.rdb同样在var/lib/redis文件中

修改完配置后我们要进行重启Redis服务,我们再进入文件夹,就能查看到aof的文件了

我们查看文件,可以按到我们之间的数据被记录在aof

2.2 AOF文件写入

当我们引入AOF之后,Redis又要在内存中写数据,又要把数据写入硬盘里的AOF文件,这样速度不会降低吗?

实际上没有影响,AOF机制并非直接把数据写入硬盘,而是写入内存中的缓冲区aof_buf,积累一段时间后再统一写入硬盘

缓冲区的刷新策略

我们可以在redis.conf文件中配置刷新策略

always频率最高,数据可靠性最高,性能最低

everysec频率中等,数据可靠性会降低,性能会提高

no频率最低,数据可靠性也是最低的,性能是最高(这是依靠操作系统进行刷新缓冲区)

2.3 AOF重写机制

AOF会把每个命令追加到AOF文件中,这样AOF文件就会持续增长,体积越来越大,那么就会影响到redis下次启动读取文件的时间,所以AOF有一个重写机制

已知AOF会记录所有的命令操作,比如

set key 111

set key 222

set key 333

这三条命令其实是冗余的,其实最后结果就是set key 333,所以我们只保留最后一条命令即可,也就是只针对最后的结果,剔除一些冗余的操作,从而达到给aof文件瘦身的效果

手动触发:调⽤ bgrewriteaof 命令。

⾃动触发:根据auto-aof-rewrite-min-size 和 auto-aof-rewrite-percentage 参数确定⾃动触发时机

  • auto-aof-rewrite-min-size:表⽰触发重写时 AOF 的最⼩⽂件⼤⼩,默认为 64MB
  • auto-aof-rewrite-percentage:代表当前 AOF 占⽤⼤⼩相⽐较上次重写时增加的⽐例

2.4 AOF重写的流程

当我们调用bgrewriteaof命令后

父进程就会调用fork(),会创建一个子进程,子进程拥有父进程的数据

在这期间父进程仍然会收到客户端的命令,这些命令会同时写入到aof_buf和aof_rewrite_buf两个缓冲区,aof_buf是上面aof机制的常规缓冲区,aof_buf里缓冲区的数据还是按照everysec策略写入到旧的AOF文件,aof_rewrite_buf是重写时的缓冲区

子进程会在内存中,遍历所有的数据,将数据写入到新创建的AOF文件

子进程写入完成之后,父进程会把aof_rewrite_buf缓冲区里重写时收到的命令再追加到新的AOF文件里

最后用新的AOF文件替换旧的AOF文件

这里最后要用新的AOF文件替换旧的AOF文件,那为什么还要把数据写入旧的AOF文件呢?

因为如果重写的新的AOF文件出现错误,最后并没有成功实现替换,这样重写时父进程收到的命令就会都丢失,所以旧的AOF文件同样得要写入数据,防止数据丢失

2.5 混合持久化

AOF是按照文本的方式来写入文件,这样后续加载的成本是比较高的,所以redis引入了"混合持久化"的方式,结合了rdb和aof的特点

混合持久化就是按照aof的方式,将每个操作记录到aof文件里,触发aof重写之后,就会把内存状态按照rdb的二进制格式写入到新的aof文件,后续的操作仍然是按照aof文本的方式追加到文件中

2.6 数据恢复

RDB和AOF都开启的时候,是读取RDB文件还是AOF文件呢?

Redis首选AOF文件,如果AOF文件存在就加载这个文件,加载成功就启动成功,如果AOF文件不存在就去加载RDB文件,这是因为AOF文件是实时性备份,数据比RDB更加全,所以首选AOF

相关推荐
松涛和鸣1 小时前
72、IMX6ULL驱动实战:设备树(DTS/DTB)+ GPIO子系统+Platform总线
linux·服务器·arm开发·数据库·单片机
likangbinlxa1 小时前
【Oracle11g SQL详解】UPDATE 和 DELETE 操作的正确使用
数据库·sql
r i c k2 小时前
数据库系统学习笔记
数据库·笔记·学习
野犬寒鸦2 小时前
从零起步学习JVM || 第一章:类加载器与双亲委派机制模型详解
java·jvm·数据库·后端·学习
IvorySQL3 小时前
PostgreSQL 分区表的 ALTER TABLE 语句执行机制解析
数据库·postgresql·开源
·云扬·3 小时前
MySQL 8.0 Redo Log 归档与禁用实战指南
android·数据库·mysql
IT邦德3 小时前
Oracle 26ai DataGuard 搭建(RAC到单机)
数据库·oracle
惊讶的猫3 小时前
redis分片集群
数据库·redis·缓存·分片集群·海量数据存储·高并发写
不爱缺氧i3 小时前
完全卸载MariaDB
数据库·mariadb
期待のcode3 小时前
Redis的主从复制与集群
运维·服务器·redis