redis---AOF持久化机制

AOF是除去RDB的另一种持久化方式,与RDB最大不同就是AOF是通过redis协议的命令记录操作感觉和mysql的二进制文件有异曲同工之处,而RDB直接存储的是键值数据。在4.0版本后还增加了混合持久化机制。

一、持久化流程

1.首先AOF持久化机制默认是不开启的,需要我们手动去设置

appendonly  yes                              (默认no,关闭)表示是否开启AOF持久化: 

appendfilename “appendonly.aof”              AOF持久化配置文件的名称:

AOF持久化策略(默认每秒):

appendfsync always                          (同步持久化,每次发生数据变更会被立即记录到磁盘,性能差但数据完整性比较好,速度慢但是安全)

appendfsync everysec                        (异步操作,每秒记录,如果一秒钟内宕机,有数据丢失)

appendfsync no                             (将缓存回写的策略交给系统,linux 默认是30秒将缓冲区的数据回写硬盘的,速度快但是没保障)

2.AOF 持久化功能的实现可以分为:命令追加(append),文件写入(write),文件同步(sync)三个步骤。
在这里插入图片描述

  • AOF 持久化需要将所有写命令记录在文件中来保存服务器状态,而文件写入操作效率比较低,如果每执行一条写命令都要写一次 AOF 文件无疑是低效的。为了提高效率,Redis 提供了一个中间层 – AOF 缓冲区,也就是说当 Redis 执行一条写命令后,先将该命令追加到 AOF 缓冲区中,在以后的某个时刻再将 AOF 缓冲区中的内容同步到文件中。Redis 在执行完一个写命令之后,会以协议格式(也就是RESP,即 Redis 客户端和服务器交互的通信协议 )将被执行的写命令追加到 Redis 服务端维护的 AOF 缓冲区末尾。下面是一段简短的AOF文件:
*2 #当前命令有两个参数
$6 #第一个参数长度是6字节,即SELECT
SELECT #当前命令的第一个参数值
$1 #当前命令的第二个参数,长度是1,即0
0  #当前命令的第二个参数值
*3
$3
SET
$12
池海描述
$9
大帅哥
*3
$3
SET
$9
sessionId
$9
123456789
*3
$9
PEXPIREAT
$9
sessionId
$13
1586411655347
*5
$4
MSET
$7
爱好2
$6
女人
$7
爱好1
$6
金钱
*2
$3
DEL
$9
sessionId
*3
$3
SET
$3
age
$2
18
*2
$4
INCR
$3
age
*3
$3
SET
$6
user:1
$7
"11111"
*2
$3
DEL
$6
user:1
*3
$3
SET
$6
user:1
$290
{"@class":"vip.chihai.common.dto.UserDto","id":1,"name":null,"username":"chihai","lastPasswordResetDate":null,"status":0,"lastLoginTime":null,"departments":null,"admin":null,"enabled":false,"authorities":null,"accountNonLocked":false,"credentialsNonExpired":false,"accountNonExpired":false}

  • AOF 缓冲区根据上面三种对应的策略向硬盘进行同步操作。不同设定操作频率也会有很大差异
  • 随着不断的写入,我们的文件就会越来越大。从而降低效率,redis提供了一种重写机制用来压缩文件。当AOF文件的大小超过了配置所设置的阙值时,Redis就会启动AOF文件压缩,只保留可以恢复数据的最小指令集,可以使用命令bgrewriteaof来手动压缩
  • 当 Redis 重启时,可以加载 AOF 文件进行数据恢复。
重写是很消耗性能的,生产中根据服务器情况进行调整
auto-aof-rewrite-percentage
auto-aof-rewrite-min-size

AOF 文件重写并不需要对现有的 AOF 文件进行任何读取、分析或者写入操作,而是通过读取服务器当前的数据库状态来实现的。首先从数据库中读取键现在的值,然后用一条命令去记录键值对,代替之前记录这个键值对的多条命令,这就是 AOF 重写功能的实现原理。就是假设一个值A没重写前记录了A的加减乘除一系列操作,重写后只记录最后运算的结果即可。省去中间一大部分不必要的过程。在实际过程中,为了避免在执行命令时造成客户端输入缓冲区溢出,AOF 重写在处理列表、哈希表、集合和有序集合这四种可能会带有多个元素的键时,会先检查键所包含的元素数量,如果数量超过 REDIS_AOF_REWRITE_ITEMS_PER_CMD ( 一般为64 )常量,则使用多条命令记录该键的值,而不是一条命令。

rewrite的触发机制:

  • 手动调用 bgrewriteaof 命令,如果当前有正在运行的 rewrite 子进程,则本次rewrite 会推迟执行,否则,直接触发一次 rewrite。
  • 通过配置指令手动开启 AOF 功能,如果没有 RDB 子进程的情况下,会触发一次 rewrite,将当前数据库中的数据写入 rewrite 文件。
  • 在 Redis 定时器中,如果有需要退出执行的 rewrite 并且没有正在运行的 RDB 或者 rewrite 子进程时,触发一次或者 AOF 文件大小已经到达配置的 rewrite 条件也会自动触发一次。

AOF 后台重写:

在这里插入图片描述
aof_rewrite 函数可以创建新的 AOF 文件,但是这个函数会进行大量的写入操作,所以调用这个函数的线程将被长时间的阻塞,因为 Redis 服务器使用单线程来处理命令请求;所以如果直接是服务器进程调用 aof_rewrite 函数的话,那么重写 AOF 期间,服务器将无法处理客户端发送来的命令请求Redis 不希望 AOF 重写会造成服务器无法处理请求,所以 Redis 决定将 AOF 重写程序放到子进程(后台)里执行。这样处理的最大好处是:

  • 子进程进行 AOF 重写期间,主进程可以继续处理命令请求;
  • 子进程带有主进程的数据副本,使用子进程而不是线程,可以避免在锁的情况下,保证数据的安全性

但是,在子进程进行 AOF 重启期间,Redis接收客户端命令,会对现有数据库状态进行修改,从而导致数据当前状态和 重写后的 AOF 文件所保存的数据库状态不一致。为此,Redis 设置了一个 AOF 重写缓冲区,这个缓冲区在服务器创建子进程之后开始使用,当 Redis 执行完一个写命令之后,它会同时将这个写命令发送给 AOF 缓冲区和 AOF 重写缓冲区。当子进程完成 AOF 重写工作之后,它会向父进程发送一个信号,父进程在接收到该信号之后,会调用一个信号处理函数,并执行以下工作:

  • 将 AOF 重写缓冲区中的所有内容写入到新的 AOF 文件中,保证新 AOF 文件保存的数据库状态和服务器当前状态一致。
  • 对新的 AOF 文件进行改名,原子地覆盖现有 AOF 文件,完成新旧文件的替换。感觉有点像JVM中的from与to关系
  • 继续处理客户端请求命令。

二、AOF 数据恢复

AOF 文件里边包含了重建 Redis 数据所需的所有写命令,所以 Redis 只要读入并重新执行一遍 AOF 文件里边保存的写命令,就可以还原 Redis 关闭之前的状态。
在这里插入图片描述

  • 创建一个不带网络连接的的伪客户端( fake client),因为 Redis 的命令只能在客户端上下文中执行,而载入 AOF 文件时所使用的的命令直接来源于 AOF 文件而不是网络连接,所以服务器使用了一个没有网络连接的伪客户端来执行 AOF 文件保存的写命令,伪客户端执行命令的效果和带网络连接的客户端执行命令的效果完全一样的。
  • 从 AOF 文件中分析并取出一条写命令。
  • 使用伪客户端执行被读出的写命令。
  • 一直执行步骤 2 和步骤3,直到 AOF 文件中的所有写命令都被处理完毕为止。
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值