Redis的AOF持久化

目录

AOF简介

AOF持久化的实现

命令追加

为什么执行完命令再写入

fsync

AOF文件的写入与同步

AOF持久化的效率和安全性

AOF文件的载入与数据还原

AOF重写

AOF文件重写的实现

AOF后台重写

Redis 4.0 对于持久化机制的优化

重点回顾

AOF与RDB的区别与优缺点与选择

Redis 的数据恢复


AOF简介

除了RDB持久化功能之外,Redis还提供了AOF (Append Only File)持久化功能。

与快照持久化相比,AOF 持久化的实时性更好,因此已成为主流的持久化方案。默认情况下 Redis 没有开启 AOF(append only file)方式的持久化,可以通过 appendonly 参数开启:

appendonly yes

与 RDB持久化通过保存数据库中的键值对来记录数据库状态不同,AOF持久化是通过保存 Redis服务器所执行的写命令来记录数据库状态的,如图

举个例子,如果我们对空白的数据库执行以下写命令,那么数据库中将包含三个键 值对:

RDB持久化保存数据库状态的方法是将msg、fruits、numbers三个键的键值对保 存到RDB文件中,而AOF持久化保存数据库状态的方法则是将服务器执行的SET、ADD、 RPUSH三个命令保存到AOF文件中。

被写入AOF文件的所有命令都是以Redis的命令请求协议格式保存的,因为Redis的命令请求协议是纯文本格式,所以我们可以直接打开一个AOF文件,观察里面的内容。

例如,对于之前执行的三个写命令来说,服务器将产生包含以下内容的AOF文件:

在这个AOF文件里面,除了用于指定数据库的SELECT命令是服务器自动添加的之外, 其他都是我们之前通过客户端发送的命令。

服务器在启动时,可以通过载入和执行AOF文件中保存的命令来还原服务器关闭之前 的数据库状态

AOF持久化的实现

AOF持久化功能的实现可以分为命令追加(append)、文件写入、文件同步(sync)三 个步骤。

命令追加

当AOF持久化功能处于打开状态时,服务器在执行完一个写命令之后,会以协议格式 将被执行的写命令追加到服务器状态的aof_buf缓冲区的末尾:

举个例子,如果客户端向服务器发送以下命令:

那么服务器在执行这个SET命令之后,会将以下协议内容追加到aof_buf缓冲区的 末尾:

以上就是AOF持久化的命令追加步骤的实现原理。

为什么执行完命令再写入

当 Redis 收到客户端修改指令后,会先进行参数校验、逻辑处理,如果没问题,就 立即 将该指令文本 存储 到 AOF 日志中,也就是说,先执行指令再将日志存盘。这一点不同于 MySQLLevelDBHBase 等存储引擎,如果我们先存储日志再做逻辑处理,这样就可以保证即使宕机了,我们仍然可以通过之前保存的日志恢复到之前的数据状态,但是 Redis 为什么没有这么做呢?

我甚至觉得没有什么特别的原因。仅仅是因为,由于AOF文件会比较大,为了避免写入无效指令(错误指令),必须先做指令检查?如何检查,只能先执行了。因为语法级别检查并不能保证指令的有效性,比如删除一个不存在的key。而MySQL这种是因为它本身就维护了所有的表的信息,所以可以语法检查后过滤掉大部分无效指令直接记录日志,然后再执行。

fsync

AOF 日志是以文件的形式存在的,当程序对 AOF 日志文件进行写操作时,实际上是将内容写到了内核为文件描述符分配的一个内存缓存中,然后内核会异步将脏数据刷回到磁盘的。

就像我们 上方第四步 描述的那样,我们需要借助 glibc 提供的 fsync(int fd) 函数来讲指定的文件内容 强制从内核缓存刷到磁盘。但 "强制开车" 仍然是一个很消耗资源的一个过程,需要 "节制"!通常来说,生产环境的服务器,Redis 每隔 1s 左右执行一次 fsync 操作就可以了。

Redis 同样也提供了另外两种策略,一个是 永不 fsync,来让操作系统来决定合适同步磁盘,很不安全,另一个是 来一个指令就 fsync 一次,非常慢。但是在生产环境基本不会使用,了解一下即可。

AOF文件的写入与同步

Redis的服务器进程就是一个事件循环(loop), 这个循环中的文件事件负责接收客户端 的命令请求,以及向客户端发送命令回复,而时间事件则负责执行像serverCron函数这 样需要定时运行的函数。

因为服务器在处理文件事件时可能会执行写命令,使得一些内容被追加到aof_buf缓冲 区里面,所以在服务器每次结束一个事件循环之前,它都会调用flushAppendOnlyFile函 数,考虑是否需要将aof_buf缓冲区中的内容写入和保存到AOF文件里面,这个过程可 以用以下伪代码表示:

flushAppendOnlyFile函数的行为由服务器配置的appendfsync选项的值来决 定,各个不同值产生的行为如表

如果用户没有主动为appendfsync选项设置值,那么appendfsync选项的默认值 为everysec, 关于appendfsync选项的更多信息,请参考Redis项目附带的示例配置 文件redis.conf。

为了提高文件的写入效率,在现代操作系统中,当用户调用write函数,将一些 数据写入到文件的时候,操作系统通常会将写入数据暂时保存在一个内存缓冲区里面, 等到缓冲区的空间被填满、或者超过了指定的时限之后,才真正地将缓冲区中的数据写 入到磁盘里面。

这种做法虽然提高了效率,但也为写

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值