redis的持久化

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

一、RDB持久化机制

RDB会定期的把我们Redis内存中的所有数据都保存到硬盘中。

RDB有定期保存有两种方式,分为手动触发自动触发

1.1手动触发

程序员通过redis客户端,执行特定的命令来触发RDB的保存

手动触发有两个指令,分别是save和bgsave

  • save : 执行save指令的时候,redis就会全力以赴的进行保存操作,此时就会阻塞redis的其他客服端的命令,导致类似于keys的后果,一般不建议使用save
  • bgsave:bg可理解为background(后面)不会影响redis服务器处理其他客服端的请求和命令

bgsave的非阻塞的实现原理,系统创建子进程来,让子进程去执行bgsave后续的保存操作,父进程继续接受客服端发来的命令。

bgsave的执行过程:

如果客服端执行bgsave命令的时候,发现系统中已经存在一个正在执行的bgsave子进程,那么就用该bgsave子进程的保存结果返回给客服端。

如果客服端执行bgsave命令的时候,发现此时没有正在执行bgsave的子进程,那么就通过fork()这样的系统调用创建出一个子进程,用于执行bgsave的保存操作。

子进程负责进行写文件,父进程继续接受客服端的请求,继续正常提供服务。

当子进程完成整体的持久化过程之后,就会通知父进程,任务完成了,父进程就会更新一些统计信息。然后子进程就可以结束销毁了。

如图:
在这里插入图片描述
RDB文件是保存在redis的默认工作目录中的,在配置文件中可以找到默认工作目录

配置文件在/etc/redis/redis.conf中

sudo vim /etc/redis/redis.conf

在这里插入图片描述
在这里插入图片描述
RDB文件默认名字:dump.rdb
在这里插入图片描述
查看该目录:
在这里插入图片描述
可以发现RDB文件保存在这。

redis服务器默认就是开启rdb的。

RDB文件时二进制文件,在保存的时候会先通过压缩,然后再存储,该过程会消耗CPU资源,但能节省存储空间。
在这里插入图片描述
注意:该文件中的内容不要随便修改,一旦把数据格式改坏了,那就会导致后续redis服务器重新启动的时候出错,因为重启时会尝试加载这个RDB文件,如果发现格式错误,就可能会导致加载数据失败。

RDB文件的检查工具:
在这里插入图片描述

RDB持久化操作是可以多次触发的原因

当执行生成RDB镜像操作的时候,此时就会把要生成的快照数据,先保存在一个临时文件中,当这个快照生成完毕之后,在删除之前的RDB文件,把新生成的临时的RDB文件名字改成刚才的dump.rdb文件。

1.2自动触发

①自动触发在满足条件的情况下才会发生,配置文件中有RDB自动触发的条件,该条件可修改。
在这里插入图片描述
默认条件是,900秒内修改一次或300秒内修改10次或60秒内修改10000次,时间和次数需要同时满足才会触发

当把条件设置为 save ”“,就表示禁止上面的条件生成快照,但后面说到的两个条件,不受影响。

注意:

  1. 虽然该条件可以修改,但是不能将条件修改得频繁触发,因为每次触发生成一次快照的成本都比较高。
  2. 也正因为如此RDB生成的不能太频繁,就导致了快照中的数据和实际的数据情况可能存在一定的偏差。

②自动触发还可以通过shutdown命令(redis中的一个命令)关闭redis服务器,也会触发(service redis-server restart)

③redis进行主从复制的时候,主节点也会自动生成RDB快照,然后把RDB快照文件内容传输给从节点(后面博客详细说明)

1.3利用RDB文件恢复redis中的内容

redis在关闭以后,内存中的内容就都释放了,当再重启的时候想要恢复原来的内容那么就需要读取RDB文件中的数据来恢复。

演示:

首先我们先创建三条key-value值,然后使用bgsave命令将它们保存到RDB文件中。
在这里插入图片描述
然后让redis服务器重启
在这里插入图片描述
最后登录redis,查看结果:
在这里插入图片描述
可以发现和我们预期的结果一样。

注意:

  1. 当我们未使用bgsave命令且自动触发条件未满足,此时使用了kill -9 命令让redis服务器异常终止,那么内存中的数据未来得及保存到RDB文件中,该数据就会丢失。
  2. 在执行完快照操作以后,前RDB文件和现RDB文件不是同一个文件,因为它们的inode不同。

当我们把RDB文件的部分改坏了,redis启动时使用该二进制文件得到的结果是不可预期的,那么redis服务器可能会不能够启动,启动了以后数据也可能是错误的。

1.4 RDB的优缺点

优点:

  • RDB 是⼀个紧凑压缩的⼆进制⽂件,代表 Redis 在某个时间点上的数据快照。⾮常适⽤于备份,全量复制等场景。⽐如每 6 ⼩时执⾏ bgsave 备份,并把 RDB ⽂件复制到远程机器或者⽂件系统中(如 hdfs)⽤于灾备。

  • Redis 加载 RDB 恢复数据远远快于 AOF 的⽅式。

缺点:

  • RDB ⽅式数据没办法做到实时持久化 / 秒级持久化。因为 bgsave 每次运⾏都要执⾏ fork 创建⼦进程,属于重量级操作,频繁执⾏成本过⾼。

  • RDB ⽂件使⽤特定⼆进制格式保存,Redis 版本演进过程中有多个 RDB 版本,兼容性可能有⻛险。

二、AOF的持久化机制

以独⽴⽇志的⽅式记录每次写命令,重启时再重新执⾏ AOF ⽂件中的命令达到恢复数据的⽬的。AOF 的主要作⽤是解决了数据持久化的实时性,⽬前已经是 Redis 持久化的主流⽅式。理解掌握好 AOF 持久化机制对我们兼顾数据安全性和性能⾮常有帮助。

2.1使用AOF

AOF默认是关闭状态的,想用使用我们需要去配置文件手动开启:

将appendonly 设置为yes即可,appendfilename 代表的是AOF文件的默认名称
在这里插入图片描述
此时将RDB文件删除掉,然后重启一下redis服务器:
在这里插入图片描述
此时再查看工作目录,可以发现AOF文件已经存在了:
在这里插入图片描述
现在我们插入几条数据:
在这里插入图片描述
然后查看AOF中的内容:
在这里插入图片描述
可以发现AOF文件中保存的都是我们输入的指令。

AOF是一个文本文件,每次进行的操作都会被记入到AOF文件中,用一些分隔符进行分隔。

2.2 AOF的执行过程

AOF机制不是直接让工作线程把数据写入硬盘,而是先写入一个内存中的缓冲区中,积累一波数据后,再统一写入硬盘中。

AOF 过程中为什么需要 aof_buf 这个缓冲区?

Redis 使⽤单线程响应命令,如果每次写 AOF ⽂件都直接同步硬盘,性能从内存的读写变成 IO 读写,必然会下降。先写⼊缓冲区可以有效减少 IO 次数,同时,Redis 还可以提供多种缓冲区同步策略,让⽤⼾根据⾃⼰的需求做出合理的平衡。

如果在缓冲区中的数据没来得及写入硬盘,那么数据是否丢了?

是的

所以redis提供了多多种AOF缓冲区同步文件策略,有参数appendfsync控制,不同值的含义如下表:

可配置值说明
always命令写⼊ aof_buf 后调⽤ fsync 同步,完成后返回。
everysec命令写⼊aof_buf 后只执⾏ write 操作,不进⾏ fsync。每秒由同步线程进⾏ fsync。
no命令写⼊ aof_buf 后只执⾏ write 操作,由 OS 控制 fsync 频率。

系统调⽤ write 和 fsync 说明:

  • write 操作会触发延迟写(delayed write)机制。Linux 在内核提供⻚缓冲区⽤来提供硬盘 IO 性能。write 操作在写⼊系统缓冲区后⽴即返回。同步硬盘操作依赖于系统调度机制,例如:缓冲区⻚空间写满或达到特定时间周期。同步⽂件之前,如果此时系统故障宕机,缓冲区内数据将丢失。

  • Fsync 针对单个⽂件操作,做强制硬盘同步,fsync 将阻塞直到数据写⼊到硬盘。

  • 配置为 always 时,每次写⼊都要同步 AOF ⽂件,性能很差,在⼀般的 SATA 硬盘上,只能⽀持⼤约⼏百 TPS 写⼊。除⾮是⾮常重要的数据,否则不建议配置。

  • 配置为 no 时,由于操作系统同步策略不可控,虽然提⾼了性能,但数据丢失⻛险⼤增,除⾮数据重要程度很低,⼀般不建议配置。

  • 配置为 everysec,是默认配置,也是推荐配置,兼顾了数据安全性和性能。理论上最多丢失 1 秒的数据。

2.3 AOF的重写机制

随着命令不断写⼊ AOF,⽂件会越来越⼤,为了解决这个问题,Redis 引⼊ AOF 重写机制压缩⽂件体积。AOF ⽂件重写是把 Redis 进程内的数据转化为写命令同步到新的 AOF ⽂件。

重写后的 AOF 为什么可以变⼩?

  • 进程内已超时的数据不再写⼊⽂件。

  • 旧的 AOF 中的⽆效命令,例如 del、hdel、srem 等重写后将会删除,只需要保留数据的最终版本。

  • 多条写操作合并为⼀条,例如 lpush list a、lpush list b、lpush list 从可以合并为 lpush list a b c。

AOF的重写可分为手动触发和自动触发

手动触发

调用bgrewriteaof命令进行重写。重写的时候不关心aof文件中原来都有什么,只关心内存中最终的数据状态。

**bgrewriteaof命令执行过程:**父进程接收到bgrewriteaof命令时,会调用fork()系统接口创建一个子进程,子进程只需要把内存中当前的数据获取出来,以AOF的格式写入到一个新的AOF文件中,父进程仍然继续接受客服端发来的命令,当fork后仍然有新的命令发来,那么父进程会维持一个aof_rewrite_buf缓冲区和aof_buf缓冲区,将fork()后的命令存放到该缓冲区中,再把aof_buf缓冲区中的值写入旧的缓冲区中,等到子进程处理完毕以后,父进程就会把新的AOF文件和aof_rewrite_buf缓冲区合并,再把旧的AOF文件和替换掉,此时保存在磁盘中的AOF文件就是我们要的文件了。
在这里插入图片描述

如果在执行bgrewriteaof的时候,当前redis正在进行aof重写,会怎么样呢?

此时不会再次执行新的aof重写,会将当前正在执行的这次重写作为结果返回。

如果在执行bgrewriteaof的时候,发现当前redis正在生成rdb文件的快照,会怎么样呢?

此时,aof重写操作就会等待,等待rdb快照生成完毕之后,再进行执行aof重写

子进程已经在重写了,父进程还需要继续写旧AOF文件吗?

需要,因为考虑到极端的情况,如果子进程重写的时候写到一半,此时服务器挂了,且父进程没有写旧的AOF文件,那么此时数据就会发生严重丢失。

自动触发

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

auto-aof-rewrite-min-size:表⽰触发重写时 AOF 的最⼩⽂件⼤⼩,默认为 64MB。

auto-aof-rewrite-percentage:代表当前 AOF 占⽤⼤⼩相⽐较上次重写时增加的⽐例。

这和RDB自动触发差不多,就是要满足条件,满足了那就触发,不满足就不触发。

三、混合持久化

在AOF重写中,我们知道AOF是按照文本的方式来写入文件的,这样的方式成本是比较高的,所以redis就引入了混合持久化的方式。

该方式结合了rdb和aof的特点。

配置文件中默认是打开的:
在这里插入图片描述
过程:

刚开始按照aof的方式把每一个请求和操作都记入文件,等到触发aof重写的时,就会把当前内存中的数据状态按照rdb的二进制格式写入新的aof文件中,后续再进行的操作仍然时按照aof文本的方式追加到文件后面的。

如:
刚开始创建两条记录:
在这里插入图片描述
此时查看appendonly.aof文件:
在这里插入图片描述
然后执行bgrewriteaof命令,进行重写:
在这里插入图片描述
再次查看appendonly.aof文件:
在这里插入图片描述
可以发现此时aof文件已经是二进制的了。

四、启动redis时数据恢复的策略

当redis上同时存在aof文件和rdb快照的时候,以aof文件为主:
在这里插入图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

冧轩在努力

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值