小学生也能看懂的Redis7持久化机制--RDB和AOF

Redis 是一个内存数据库,所以其运行效率非常高。但也存在一个问题:内存中的数据 是不持久的,若主机宕机或 Redis 关机重启,则内存中的数据全部丢失。因此 Redis 具有持久化功能Redis通过数据快照或追加操作日志的形式将数据持久化到磁盘。 根据持久化使用技术的不同,Redis 的持久化分为两种:RDB 与 AOF

Redis 持久化也称为钝化,是指将内存中数据库的状态描述信息保存到磁盘中。只不过不同的持久化技术,对数据的状态描述信息不同,生成的持久化文件也不同。但它们的作用都是相同的:避免数据意外丢失 。

当系统重新启动时,会自动加载持久化文件,并根据文件中数据库状态描述信息将数据恢复到内存中,这个数据恢复过程也称为激活。这个钝化与激活的过程就是 Redis 持久化的基本原理。

1.RDB

RDB(Redis DataBase)是Redis默认开启的持久化⽅式,是指将内存中某一时刻的数据快照全量写入到指定的 rdb 文件中。当 Redis 启动时会自动读取rdb快照文件,将数据从硬盘载入到内存,以恢复 Redis 关机前的数据库状态。

由于RDB是生成的数据快照,因此⽣成的 RDB⽂件⾮常适合⽤于全量复制、数据备份等场景

RDB创建数据快照的时间间隔可以通过redis.conf配置文件中的"save"配置选项进⾏设置或者通过命令即时创建快照,如"save 900 1"表示如果900秒内有⾄少1个key变化,则创建⼀个snapshots快照。

Redis6到7配置文件的变化之一就是Redis7相对Redis6不需要频繁的保存快照。

1.1 RDB3种持久化方式

通过 lastsave 命令可以查看最近一次执行持久化的时间,其返回的是一个 Unix 时间戳。

手动save

执行 save 命令可立即进行一次持久化保存。save 命令由Redis主进程执行,执行期间会阻塞 redis-server 进程,直至持久化过程完毕。而在 redis-server 进程阻塞期间,Redis 不能处理任何读写请求,无法对外提供服务。

手动bgsave

执行 bgsave 命令可立即进行一次持久化保存。不同于 save 命 令的是,正如该命令的名称一样,background save,后台运行 save。bgsave 命令会使服务器主进程 redis-server 生成一个子进程,由该子进程负责完成保存过程。在子进程进行保存过程 中,不会阻塞 redis-server 进程对客户端读写请求的处理

自动bgsave

自动条件触发的本质仍是 bgsave 命令的执行。只不过是用户通过在配置文件中做相应 的设置后,Redis 会根据设置信息自动调用 bgsave 命令执行。

1.2 RDB几个主要配置

RDB 相关的配置在 redis.conf 文件的 SNAPSHOTTING 部分

save

stop-write-on-bgsave-error

rdbcompression

rdbchecksum

sanitize-dump-payload

rdb-del-sync-files

1.3 RDB文件结构

  • SOF
    一个常量,一个字符串 REDIS,仅包含这五个字符,其长度为 5。用于标识 RDB 文件的开始,以便在加载 RDB 文件时可以迅速判断出文件是否是 RDB 文件。
  • rdb_version
    一个整数,长度为 4 字节,表示 RDB 文件的版本号
  • EOF
    一个常量,占 1 个字节,用于标识 RDB 数据的结束,校验和的开始。
  • check_sum
    校验和check_sum 用于校验 RDB 文件中的内容是否出现数据异常,采用CRC算法,后面讲到
  • databases

    • databases 是 RDB 文件中最重要的数据部分,可以包含任意多个非空数据库。而 每个 database 又是由三部分构成:
              1. SODB:一个常量,占 1 个字节,用于标识一个数据库的开始。
              2. db_number:数据库编号。
              3. key_value_pairs:当前数据库中的键值对数据。

              每个 key_value_pairs 由很多个用于描述键值对的数据构成。
                      1. VALUE_TYPE:一个常量,占 1 个字节,用于标识该键值对中 value 的类型。
                      2. EXPIRETIME_UNIT:一个常量,占 1 个字节,用于标识过期时间的单位是秒还是毫秒。
                      3. time:当前 key-value 的过期时间。

1.4 CRC数据异常校验算法

        持久化时,先将 SOF、rdb_version 、内存数据库中的数据快照这三者的二进制数据拼接起来,形成一个二进制数(假设称为数 a),然后再使用这个 a 除以校验和 check_sum,得到一个余数 b,然后再将b 拼接到 a 的后面,形成 databases

         加载时,需要先使用 check_sum 对 RDB 文件进行数据损坏验证验证过程:只需将 RDB 文件中除 EOF 与 check_sum 外的数据除以 check_sum。只要除得的余数不是 0,就说明文件发生损坏。当然,如果余数是 0,也不能肯定文件没有损坏。 这种验证算法,是数据损坏校验,而不是数据没有损坏的校验。

1.5 RDB持久化过程

对于默认的RDB持久化,采用的是bgsave命令,redis-server 进程会 fork 出一 个 bgsave 子进程,由该子进程以异步方式负责完成持久化。

bgsave 子进程的详细工作原理如下:

由于子进程可以继承父进程的所有资源,且父进程不能拒绝子进程的继承权。所以, bgsave 子进程有权读取到 redis-server 进程写入到内存中的用户数据。 bgsave 子进程在持久化时首先会将内存中的全量数据 copy 到磁盘中的一个 RDB 临时文件,copy 结束后,再将该文件 rename 为 dump.rdb,替换掉原来的同名文件。

在进行持久化过程中,如果 redis-server 进程接收到了用户写请求,则系统会将内存中发生数据修改的物理块 copy 出一个副本。等内存中的全量数据 copy 结束后,会再将 副本中的数据 copy 到 RDB 临时文件。这个副本的生成是由于 Linux 系统的写时复制技术 (Copy-On-Write)实现的。

2.AOF

AOF 持久性记录服务器接收到的每个写操作。然后在服务器启动时再次重复执行这些操作,从⽽重建原始数据集。命令使⽤与 Redis 协议本身相同的格式进⾏记录。

2.1 AOF几个主要配置

开启AOF

appendfilename

Redis 7 在这里发生了重大变化。原来只有一个 appendonly.aof 文件,现在具有了三类多个 文件:

  • 基本文件:可以是 RDB 格式也可以是 AOF 格式。其存放的内容是由 RDB 转为 AOF 当 时内存的快照数据。该文件可以有多个
  • 增量文件:扩展名是.aof,以操作日志形式记录转为 AOF 后的写入操作。该文件可以有多个。
  • 清单文件:用于维护 AOF 文件的创建顺序,保障激活时的应用顺序。该文件只有一个。

appenddirname

为了方便管理,可以专门为 AOF 持久化文件指定存放目录。目录名由 appenddirname 属性指定,存放在 redis.conf 配置文件的 dir 属性指定的目录,默认为 Redis 安装目录。

appendfsync

当客户端提交写操作命令后,该命令就会写入到 aof_buf 中,而 aof_buf 中的数据持久化到磁盘 AOF 文件的过程称为数据同步。

何时将 aof_buf 中的数据同步到 AOF 文件?采用不同的数据同步策略,有三种策略:

  • always
    写操作命令写入 aof_buf 后会立即调用 fsync()系统函数,将其追加到 AOF 文件。 该策略效率较低,但相对比较安全,不会丢失太多数据。最多就是刚刚执行过的写操作 在尚未同步时出现宕机或重启,将这一操作丢失。
  • no
    写操作命令写入 aof_buf 后什么也不做,不会调用 fsync()函数。而将 aof_buf 中的 数据同步磁盘的操作由操作系统负责。Linux 系统默认同步周期为 30 秒。效率较高。
  • everysec
    默认策略,写操作命令写入 aof_buf 后并不直接调用 fsync(),而是每秒调用 一次 fsync()系统函数来完成同步。该策略兼顾到了性能与安全,是一种折中方案。

no-appendfsync-on-rewrite 

该属性用于指定,当 AOF fsync 策略设置为 always 或 everysec,当主进程创建了子进程 正在执行 bgsave 或 bgrewriteaof 时,主进程是否不调用 fsync()来做数据同步。设置为 no, 双重否定即肯定,主进程会调用 fsync()做同步。而 yes 则不会调用 fsync()做数据同步。 如果调用 fsync(),在需要同步的数据量非常大时,会阻塞主进程对外提供服务,即会存在延迟问题。如果不调用 fsync(),则 AOF fsync 策略相当于设置为了 no,可能会存在 30 秒 数据丢失的风险。

aof-rewrite-incremental-fsync 

当 bgrewriteaof 在执行过程也是先将 rewrite 计算的结果写入到了 aof_rewrite_buf 缓存,中,然后当缓存中数据达到一定量后就会调用 fsync()进行刷盘操作,即数据同步,将数据写 入到临时文件。该属性用于控制 fsync()每次刷盘的数据量最大不超过 4MB。这样可以避免由 于单次刷盘量过大而引发长时间阻塞。

aof-load-truncated 

在进行 AOF 持久化过程中可能会出现系统突然宕机的情况,此时写入到 AOF 文件中的 最后一条数据可能会不完整。当主机启动后,Redis 在 AOF 文件不完整的情况下是否可以启 动,取决于属性 aof-load-truncated 的设置。其值为:

  • yes:AOF 文件最后不完整的数据直接从 AOF 文件中截断删除,不影响 Redis 的启动。
  • no:AOF 文件最后不完整的数据不可以被截断删除,Redis 无法启动。

aof-timestamp-enabeld

该属性设置为 yes 则会开启在 AOF 文件中增加时间戳的显示功能,可方便按照时间对数 据进行恢复。但该方式可能会与 AOF 解析器不兼容,所以默认值为 no,不开启。

2.2 AOF持久化过程

  1. Redis 接收到的写操作命令并不是直接追加到磁盘的 AOF 文件的,而是将每一条写命令 按照 redis 通讯协议格式暂时添加到 AOF 缓冲区 aof_buf
  2. 根据设置的数据同步策略,当同步条件满足时,再将缓冲区中的数据一次性写入磁盘的 AOF 文件,以减少磁盘 IO 次数,提高性能。
  3. 当磁盘的 AOF 文件大小达到了 rewrite 条件时,redis-server 主进程会 fork 出一个子进程 bgrewriteaof,由该子进程完成 rewrite 过程。
  4. 子进程 bgrewriteaof 首先对该磁盘 AOF 文件进行 rewrite 计算,将计算结果写入到一个 临时文件,全部写入完毕后,再 rename 该临时文件为磁盘文件的原名称,覆盖原文件。
  5. 如果在 rewrite 过程中又有写操作命令追加,那么这些数据会暂时写入 aof_rewrite_buf 缓冲区。等将全部 rewrite 计算结果写入临时文件后,会先将 aof_rewrite_buf 缓冲区中 的数据写入临时文件,然后再 rename 为磁盘文件的原名称,覆盖原文件。 

2.3 AOF文件格式 

AOF 文件包含三类文件:基本文件、增量文件与清单文件。其中基本文件一般为 rdb 格式,在前面已经研究过了。下面就来看一下增量文件与清单文件的内容格式。

增量文件

增量文件扩展名为.aof,采用 AOF 格式。AOF 格式其实就是 Redis 通讯协议格式AOF 持久化文件的本质就是基于 Redis 通讯协议的文本,将命令以纯文本的方式写入到文件中。

Redis 协议规定,Redis 文本是以行来划分,每行以\r\n 行结束。每一行都有一个消息头, 以表示消息类型。消息头由六种不同的符号表示,其意义如下:

  • (+) 表示一个正确的状态信息
  • (-) 表示一个错误信息
  • (*) 表示消息体总共有多少行,不包括当前行
  • ($) 表示下一行消息数据的长度,不包括换行符长度\r\n
  • (空) 表示一个消息数据
  • (:) 表示返回一个数值

查看AOF文件 

清单文件

2.4 Rewrite压缩机制

随着使用时间的推移,AOF 文件会越来越大。为了防止 AOF 文件由于太大而占用大量 的磁盘空间,降低性能,Redis 引入了 Rewrite 机制来对 AOF 文件进行压缩。

所谓 Rewrite 其实就是对 AOF 文件进行重写整理。当 Rewrite 开启后,主进程 redis-server 创建出一个子进程 bgrewriteaof,由该子进程完成 rewrite 过程。其首先对现有 aof 文件进行 rewrite 计算,将计算结果写入到一个临时文件,写入完毕后,再 rename 该临时文件为原 aof 文件名,覆盖原有文件。在 rewrite 期间,redis-server 仍是可以对外提供读写服务的。

 rewrite 计算也称为 rewrite 策略。rewrite 计算遵循以下策略:

  •  读操作命令不写入文件
  •  无效命令不写入文件
  •  过期数据不写入文件
  •  多条命令合并写入文件

开启rewrite

  • 手动:执行bgrewriteaof命令
  • 自动:修改配置文件

  1. auto-aof-rewrite-percentage:开启 rewrite 的增大比例,默认 100%,当 AOF 日志文件大小增长到指定的百分比时,Redis 主进程 redis-server 会 fork 出一个子进程 bgrewriteaof 来完成 rewrite 过程。指定为 0,表示禁用自动 rewrite。
  2. auto-aof-rewrite-min-size:开启 rewrite 的 AOF 文件最小值,默认 64M。该值的设置主 要是为了防止小 AOF 文件被 rewrite,从而导致性能下降。

rewrite工作原理

Redis 会记住最新 rewrite 后的 AOF 文件大小作为基本大小,如果从主机启动后就没有发生过重写,则基本大小就使用启动时 AOF 的大小。 如果当前 AOF 文件大于基本大小的配置文件中指定的百分比阈值,且当前 AOF 文件大 于配置文件中指定的最小阈值,则会触发 rewrite。

3.RDB+AOF

Redis7提供了新的持久化模式:RDB + AOF

混合式持久化开启

 对于基本文件可以是 RDF 格式也可以是 AOF 格式。通过 aof-use-rdb-preamble 属性可以选择。其默认值为 yes,即默认 AOF 持久化的基本文件为 rdb 格式文件,也就是默认采用混合式持久化。

4.RDB和AOF对比

https://blog.csdn.net/chuanxincui/article/details/89306882

  • AOF,存放的指令日志,做数据恢复的时候,其实是要回放和执行所有的指令日志,来恢复出来内存中的所有数据的;
  • RDB,就是一份数据文件,恢复的时候,直接加载到内存中即可;
  • RDB无法实现实时或者秒级持久化,是间隔一段时间进行持久化,如果持久化时Redis发生故障,会发生数据丢失,而AOF可以做到每隔一秒记录一次日志,因此数据安全性高,也正因为AOF每秒记录一次日志,因此AOF文件通常比RDB大,所以AOF有了rewrite压缩机制。
  • 17
    点赞
  • 10
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值