Redis 持久化AOF与RDB

Redis为什么需要持久化?

思考这个问题我觉得可以反向思考,假设Redis不支持持久化的话,会有什么后果。
首先Redis是基于内存的数据库,一旦Redis服务宕机或是重启,那么Redis中的数据就会立马丢失,此时所有数据的请求都会到达后端数据库,给数据库造成巨大压力,从而造成性能的下降甚至后端数据库的宕机,导致系统的瘫痪。

而Redis支持两种持久化方案分别是AOF日志和RDB快照

AOF日志

和MySql不一样,Redis是“写后”日志,Redis先执行命令,把数据写入内存,然后才记录日志。日志里记录的是Redis收到的每一条命令,这些命令是以文本形式保存

为什么要采用写后日志

  • 避免检查开销
  • 不会阻塞当前的写操作

写后日志缺点

  • 在写日志之前宕机的话,会丢失数据
  • 主线程写磁盘压力大,导致写盘慢,影响后续操作

开启AOF日志

默认情况下AOF是关闭的,可以在配置文件 redis.conf 开启AOF日志

# appendonly参数开启AOF持久化
appendonly no
# AOF持久化的文件名,默认是appendonly.aof
appendfilename "appendonly.aof"

AOF的实现

Redis是基于内存的数据库,在每次写操作之后,如果要写入AOF日志的话,需要再从内核态切换到用户态写入磁盘。所以如何实现AOF是影响性能一大关键。
AOF日志记录Redis的每个写命令,步骤分为:命令追加(append)、文件写入(write)和文件同步(sync)。

  • 命令追加:
    • 当AOF持久化功能打开了,服务器在执行完一个写命令之后,会以协议格式将被执行的写命令追加到服务器的 aof_buf 缓冲区。
  • 文件写入和同步:
    • 关于何时将 aof_buf 缓冲区的内容写入AOF文件中,Redis提供了三种写回策略: 在这里插入图片描述
      Always : 同步写回:每个写命令执行完,立马同步地将日志写回磁盘;
      Everysec: 每秒写回:每个写命令执行完,只是先把日志写到AOF文件的内存缓冲区,每隔一秒把缓冲区中的内容写入磁盘;
      No:操作系统控制的写回:每个写命令执行完,只是先把日志写到AOF文件的内存缓冲区,由操作系统决定何时将缓冲区内容写回磁盘。

AOF重写

随着对Redis的操作的增多,AOF文件也会越来越大,这里面会有许多冗余或是对当前数据没有任何影响的命令(比如写入修改后又把这条数据删了),这样的命令只会占用空间和影响Redis数据恢复,所以AOF重写就是创建一个新的AOF文件来替换现有的AOF文件,两个文件命令执行后产生的数据相同,但是新的AOF文件没有冗余命令。

AOF重写机制

AOF重写是由主线程fork出后台的bgrewriteaof子进程,fork会把主线程的内存拷贝一份给bgrewriteaof子进程,这里面就包含了数据库的最新数据。然后bgrewriteaof子进程就可以在不影响主线程的情况下逐一把拷贝的数据写成操作,计入重写日记。

所以aof在重写时,fork进程时是会阻塞主线程的。

AOF日志何时会重写

有两个配置项控制AOF重写的触发:
auto-aof-rewrite-min-size: 表示运行AOF重写时文件的最小大小,默认为64MB。
auto-aof-rewrite-percentage: 这个值的计算方式是,当前aof文件大小和上一次重写后aof文件大小的差值,再除以上一次重写后aof文件大小。也就是当前aof文件比上一次重写后aof文件的增量大小,和上一次重写后aof文件大小的比值。

在重写日志整个过程时,主线程有哪些地方会被阻塞?

  1. fork子进程时,需要拷贝虚拟页表,会对主线程阻塞。
  2. 主进程有bigkey写入时,操作系统会创建页面的副本,并拷贝原有的数据,会对主线程阻塞。
  3. 子进程重写日志完成后,主进程追加aof重写缓冲区时可能会对主线程阻塞。

为什么AOF重写不复用原AOF日志

  1. 父子进程写同一个文件会产生竞争问题,影响父进程的性能。
  2. 如果AOF重写过程中失败了,相当于污染了原本的AOF文件,无法做恢复数据使用

RDB快照

RDB快照是将Redis某一刻的数据保存到磁盘上的方案,而由于是某一刻的数据,所以RDB的数据有可能是早于Redis此刻的数据的
RDB快照后会生成一个二进制文件,存储的是Redis快照时刻的数据,二进制文件,因此Redis从RDB文件恢复数据的速度比从AOF日志文件恢复速度快很多。但没有可读性

RDB触发方式

RDB快照有两种触发方式:分别是手动触发和自动触发

手动触发

手动触发有两个命令 savebgsave

  • save命令
    • save命令会阻塞当前Redis服务,知道完成RDB的快照,因此当数据量较大时可能会导致长时间的阻塞,不建议在线上环境使用
  • bgsave命令
    • Redis进程执行fork操作创建子进程,RDB持久化过程由子 进程负责,完成后自动结束。阻塞只发生在fork阶段,一般时间很短

bgsave具体流程如下:

  1. redis客户端执行bgsave命令或者自动触发bgsave命令;
  2. 主进程判断当前是否已经存在正在执行的子进程,如果存在,那么主进程直接返回;
  3. 如果不存在正在执行的子进程,那么就fork一个新的子进程进行持久化数据,fork过程是阻塞的,fork操作完成后主进程即可执行其他操作;
  4. 子进程先将数据写入到临时的rdb文件中,待快照数据写入完成后再原子替换旧的rdb文件;
  5. 同时发送信号给主进程,通知主进程rdb持久化完成,主进程更新相关的统计信息(info Persitence下的rdb_*相关选项)。

自动触发

在以下4种情况时会自动触发

  1. redis.conf中配置save m n,即在m秒内有n次修改时,自动触发bgsave生成rdb文件;
  2. 主从复制时,从节点要从主节点进行全量复制时也会触发bgsave操作,生成当时的快照发送到从节点;
  3. 执行debug reload命令重新加载redis时也会触发bgsave操作;
  4. 默认情况下执行shutdown命令时,如果没有开启aof持久化,那么也会触发bgsave操作

redis.conf 配置文件
redis.conf文件中有默认的 save m n配置, save m n 的配置的意思是:当m秒内有n条key信息的变化时bgsave操作,虽然配置写的是save但是执行的是bgsave操作来进行RDB快照;

当bgsave期间有操作对Redis数据进行修改了的话,如何保证数据的一致性呢?

RDB每次fork一个进程去进行快照时,由于数据量经常容易比较大因此可能会持续较长的时间,这段时间里Redis服务依然运行,有写或是修改的操作也是经常,那么此时如何保证RDB文件数据的一致性。

实际上RDB操作的思路时Copy-on-Write,当快照期间有数据发生变化时,fork子进程会对这些发生改变的数据创建一个副本,存放到内存的另一个区域,当快照结束后子进程再将该副本写到RDB文件。

当bgsave期间服务崩溃了数据会丢失吗?

bgsave期间服务崩溃的话,那么这次RDB快照就失败了,但是这并不会影响上次的快照文件,RDB快照并不是直接写入覆盖上一次快照的RDB文件,而是先写入一个新的临时数据文件,当RDB快照成功完成之后才会替换掉原先的文件。所以当bgsave期间服务崩溃了的话最多只会丢失上次RDB到崩溃期间的数据。可以从上一次的RDB文件恢复数据

RDB和AOF混合方式

Redis 4.0 中提出了一个混合使用 AOF 日志和内存快照的方法。简单来说,内存快照以一定的频率执行,在两次快照之间,使用 AOF 日志记录这期间的所有命令操作

RDB和AOF是怎么个混合法?

已知,RDB快照执行时间长,且不适合实时持久化,但RDB文件小,恢复数据快。AOF可以实时持久化,丢失的数据少,但是日志文件大。

例:在一次全量快照后,使用AOF日志记录数据,在经过几次的修改,再去进行全量快照,此时的快照已经有了全部数据,那么AOF文件就可以不用了,就可以删除了。如此一来,不仅全量快照的次数少了,AOF文件也没那么大,可以减少AOF重写,恢复文件速度也更快了。既能享受到 RDB 文件快速恢复的好处,又能享受到 AOF 只记录操作命令的简单优势, 实际环境中用的很多

恢复数据

在这里插入图片描述

  1. redis重启时判断是否开启aof,如果开启了aof,那么就优先加载aof文件;
  2. 如果aof存在,那么就去加载aof文件,加载成功的话redis重启成功,如果aof文件加载失败,那么会打印日志表示启动失败,此时可以去修复aof文件后重新启动;
  3. 若aof文件不存在,那么redis就会转而去加载rdb文件,如果rdb文件不存在,redis直接启动成功;
  4. 如果rdb文件存在就会去加载rdb文件恢复数据,如加载失败则打印日志提示启动失败,如加载成功,那么redis重启成功,且使用rdb文件恢复数据

参考文章:https://pdai.tech/md/db/nosql-redis/db-redis-x-rdb-aof.html

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值