Redis持久化——AOF机制详解

本文涉及的产品
云数据库 Tair(兼容Redis),内存型 2GB
Redis 开源版,标准版 2GB
推荐场景:
搭建游戏排行榜
日志服务 SLS,月写入数据量 50GB 1个月
简介: Redis提供了RDB和AOF的持久化选项。本文主要介绍AOF的核心概念、同步步骤、保存模式、AOF重写详解及AOF的优缺点,还介绍了RDB和AOF混合方式的运行机制。AOF(Append Only File):以协议文本的方式,将所有对数据库进行过写入的命令(及其参数)记录到 AOF 文件,以此达到记录数据库状态的目的

在运行情况下,Redis 以数据结构的形式将数据维持在内存中,为了让这些数据在 Redis 重启之后仍然可用,需要将数据写入持久存储

持久化是指将数据写入持久存储,例如固态磁盘(SSD)

Redis 提供了一系列持久化选项。这些包括:

  • RDB(Redis Database):将数据库的快照(snapshot)以二进制的方式保存到磁盘中
  • AOF(Append Only File):以协议文本的方式,将所有对数据库进行过写入的命令(及其参数)记录到 AOF 文件,以此达到记录数据库状态的目的
  • RDB + AOF:RDB和AOF混合方式(4.0版本)

RDB详解见Redis持久化——RDB机制详解

AOF

本文首先介绍 AOF 功能的运作机制,了解命令是如何被保存到 AOF 文件里的,观察不同的 AOF 保存模式对数据的安全性、以及 Redis 性能的影响。

之后会介绍从 AOF 文件中恢复数据库状态的方法,以及该方法背后的实现机制。

最后还会介绍对 AOF 进行重写以调整文件体积的方法,并研究这种方法是如何在不改变数据库状态的前提下进行的

在这里插入图片描述

AOF文件使用网络通讯协议的格式来保存这些命令

AOF例子

若执行以下命令:

redis> RPUSH list 1 2 3 4
(integer) 4

redis> LRANGE list 0 -1
1) "1"
2) "2"
3) "3"
4) "4"

redis> KEYS *
1) "list"

redis> RPOP list
"4"

那么其中两条对数据库有修改的写入命令就会被同步到 AOF 文件中:

RPUSH list 1 2 3 4

RPOP list

上面列举的两个命令在 AOF 文件实际保存如下:

*2
$6
SELECT
$1
0
*6
$5
RPUSH
$4
list
$1
1
$1
2
$1
3
$1
4
*2
$4
RPOP
$4
list

除了 SELECT 命令是 AOF 程序自己加上去的之外, 其他命令都是之前我们在终端里执行的命令

*表示后面语句的词个数,$表示后面词的字节数

AOF同步步骤

同步命令到 AOF 文件的整个过程可以分为三个阶段:

  1. 命令传播: Redis 将执行完的命令、命令的参数、命令的参数个数等信息发送到 AOF 程序中
  2. 缓存追加: AOF 程序根据接收到的命令数据,将命令转换为网络通讯协议的格式,然后将协议内容追加到服务器的 AOF 缓存中
  3. 文件写入和保存: AOF 缓存中的内容被写入到 AOF 文件末尾,如果设定的 AOF 保存条件被满足的话,fsync函数或者fdatasync函数会被调用,将写入的内容真正地保存到磁盘中

命令传播

当一个 Redis 客户端需要执行命令时,它通过网络连接,将协议文本发送给 Redis 服务器

比如说,要执行命令SET KEY VALUE,客户端将向服务器发送文本*3\r\n$3\r\nSET\r\n$3\r\nKEY\r\n$5\r\nVALUE\r\n

服务器在接到客户端的请求之后,它会根据协议文本的内容,选择适当的命令函数,并将各个参数从字符串文本转换为 Redis 字符串对象(StringObject)

每当命令函数成功执行之后, 命令参数都会被传播到 AOF 程序, 以及 REPLICATION 程序

命令传播过程图

缓存追加

当命令被传播到 AOF 程序之后,程序会根据命令以及命令的参数,将命令从字符串对象转换回原来的协议文本

缓存追加过程可以分为以下三步:

  1. 接受命令、命令的参数、以及参数的个数、所使用的数据库等信息
  2. 将命令还原成 Redis 网络通讯协议
  3. 将协议文本追加到aof_buf末尾

协议文本生成之后,它会被追加到redis.h/redisServer结构的aof_buf末尾

redisServer结构维持着 Redis 服务器的状态,aof_buf域则保存着所有等待写入到 AOF 文件的协议文本

struct redisServer {

    // 其他域...

    sds aof_buf;

    // 其他域...
};

文件写入和保存

每当服务器常规任务函数被执行、或者事件处理器被执行时,aof.c/flushAppendOnlyFile函数都会被调用,这个函数执行以下两个工作:

  • WRITE:根据条件,将aof_buf中的缓存写入到 AOF 文件
  • SAVE:根据条件,调用fsyncfdatasync函数,将 AOF 文件保存到磁盘中

两个步骤都需要根据一定的条件来执行 而这些条件由 AOF 所使用的保存模式来决定。以下会介绍 AOF 所使用的三种保存模式,以及在这些模式下,步骤WRITE和SAVE的调用条件

AOF 保存模式

Redis 目前支持三种 AOF 保存模式

  • Always,同步写回:每个写命令执行完,立马同步地将日志写回磁盘
  • Everysec,每秒写回:每个写命令执行完,只是先把日志写到AOF文件的内存缓冲区,每隔一秒把缓冲区中的内容写入磁盘
  • No,操作系统控制的写回:每个写命令执行完,只是先把日志写到AOF文件的内存缓冲区,由操作系统决定何时将缓冲区内容写回磁盘

保存模式优缺点

AOF重写

根据键的类型,使用适当的写入命令来重现键的当前值,这就是 AOF 重写的实现原理

所谓的“重写”其实是一个有歧义的词语,实际上 AOF 重写并不需要对原有的 AOF 文件进行任何写入和读取,它针对的是数据库中键的当前值

AOF重写图例

AOF后台重写

AOF 重写是一个有歧义的名字,实际的重写工作是针对数据库的当前值来进行的,程序既不读写、也不使用原有的 AOF 文件

AOF 后台重写,是为了避免主进程被阻塞,无法处理请求,所以采用主进程fork出子进程,用于 AOF 重写。为了避免在 AOF 重写期间新命令对现有数据的修改导致的不一致问题,Redis 增加了一个AOF 重写缓存,这个缓存在fork出子进程之后开始启用,Redis 主进程在接到新的写命令之后,除了会将这个写命令的协议内容追加到现有的 AOF 文件之外,还会追加到这个缓存中

在这里插入图片描述

换言之, 当子进程在执行 AOF 重写时, 主进程需要执行以下三个工作:

  1. 处理命令请求
  2. 将写命令追加到现有的 AOF 文件中
  3. 将写命令追加到 AOF 重写缓存中

当子进程完成 AOF 重写之后,它会向主进程发送一个完成信号,主进程在接到完成信号之后,会调用一个信号处理函数,并完成以下工作:

  1. 将 AOF 重写缓存中的内容全部写入到新 AOF 文件中。
  2. 对新的 AOF 文件进行改名,覆盖原有的 AOF 文件

以上就是 AOF 后台重写, 也即是BGREWRITEAOF命令的工作原理

AOF优缺点

  • 优点
    • 拥有不同的fsync策略,fsync是使用后台线程执行的,写入性能很好
    • AOF是一个仅追加日志,没有查找和断电时的损坏问题。即使由于某种原因(磁盘已满或其他原因)日志以写入一半的命令结束,redis-check-aof工具也能够轻松修复它
    • 当 AOF 变得太大时,Redis 能够在后台自动重写 AOF
    • AOF 以易于理解和解析的格式包含一个接一个地记录所有操作的日志,使得导出和恢复十分简单
  • 缺点

    • 对于相同的数据集,AOF 文件通常比等效的 RDB 文件大
    • 根据确切的 fsync 策略,AOF 可能比 RDB 慢

      Redis < 7.0

    • 如果在重写期间有对数据库的写入,AOF 会使用大量内存
    • 重写期间到达的所有写入命令都会写入磁盘两次
    • Redis 可能会在重写结束时冻结写入并将这些写入命令同步到新的 AOF 文件

RDB和AOF混合方式(4.0版本)

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

这样一来,快照不用很频繁地执行,这就避免了频繁 fork 对主线程的影响。而且,AOF 日志也只用记录两次快照间的操作,也就是说,不需要记录所有操作了,因此,就不会出现文件过大的情况了,也可以避免重写开销。

如下图所示,T1 和 T2 时刻的修改,用 AOF 日志记录,等到第二次做全量快照时,就可以清空 AOF 日志,因为此时的修改都已经记录到快照中了,恢复时就不再用日志了。

这个方法既能享受到 RDB 文件快速恢复的好处,又能享受到 AOF 只记录操作命令的简单优势, 实际环境中用的很多。


参考资料:

  1. Redis persistence
  2. Redis 设计与实现
  3. Redis持久化详解
相关实践学习
基于Redis实现在线游戏积分排行榜
本场景将介绍如何基于Redis数据库实现在线游戏中的游戏玩家积分排行榜功能。
云数据库 Redis 版使用教程
云数据库Redis版是兼容Redis协议标准的、提供持久化的内存数据库服务,基于高可靠双机热备架构及可无缝扩展的集群架构,满足高读写性能场景及容量需弹性变配的业务需求。 产品详情:https://www.aliyun.com/product/kvstore &nbsp; &nbsp; ------------------------------------------------------------------------- 阿里云数据库体验:数据库上云实战 开发者云会免费提供一台带自建MySQL的源数据库&nbsp;ECS 实例和一台目标数据库&nbsp;RDS实例。跟着指引,您可以一步步实现将ECS自建数据库迁移到目标数据库RDS。 点击下方链接,领取免费ECS&amp;RDS资源,30分钟完成数据库上云实战!https://developer.aliyun.com/adc/scenario/51eefbd1894e42f6bb9acacadd3f9121?spm=a2c6h.13788135.J_3257954370.9.4ba85f24utseFl
相关文章
|
11天前
|
监控 NoSQL 测试技术
【赵渝强老师】Redis的AOF数据持久化
Redis 是内存数据库,提供数据持久化功能,支持 RDB 和 AOF 两种方式。AOF 以日志形式记录每个写操作,支持定期重写以压缩文件。默认情况下,AOF 功能关闭,需在 `redis.conf` 中启用。通过 `info` 命令可监控 AOF 状态。AOF 重写功能可有效控制文件大小,避免性能下降。
|
11天前
|
存储 监控 NoSQL
【赵渝强老师】Redis的RDB数据持久化
Redis 是内存数据库,提供数据持久化功能以防止服务器进程退出导致数据丢失。Redis 支持 RDB 和 AOF 两种持久化方式,其中 RDB 是默认的持久化方式。RDB 通过在指定时间间隔内将内存中的数据快照写入磁盘,确保数据的安全性和恢复能力。RDB 持久化机制包括创建子进程、将数据写入临时文件并替换旧文件等步骤。优点包括适合大规模数据恢复和低数据完整性要求的场景,但也有数据完整性和一致性较低及备份时占用内存的缺点。
|
1月前
|
存储 缓存 NoSQL
大数据-45 Redis 持久化概念 RDB AOF机制 持久化原因和对比
大数据-45 Redis 持久化概念 RDB AOF机制 持久化原因和对比
39 2
大数据-45 Redis 持久化概念 RDB AOF机制 持久化原因和对比
|
1月前
|
设计模式 NoSQL 网络协议
大数据-48 Redis 通信协议原理RESP 事件处理机制原理 文件事件 时间事件 Reactor多路复用
大数据-48 Redis 通信协议原理RESP 事件处理机制原理 文件事件 时间事件 Reactor多路复用
37 2
|
1月前
|
消息中间件 分布式计算 NoSQL
大数据-41 Redis 类型集合(2) bitmap位操作 geohash空间计算 stream持久化消息队列 Z阶曲线 Base32编码
大数据-41 Redis 类型集合(2) bitmap位操作 geohash空间计算 stream持久化消息队列 Z阶曲线 Base32编码
27 2
|
1月前
|
存储 缓存 NoSQL
大数据-46 Redis 持久化 RDB AOF 配置参数 混合模式 具体原理 触发方式 优点与缺点
大数据-46 Redis 持久化 RDB AOF 配置参数 混合模式 具体原理 触发方式 优点与缺点
59 1
|
6月前
|
NoSQL 关系型数据库 MySQL
Redis持久化机制 RDB 和 AOF 的选择
Redis持久化机制 RDB 和 AOF 的选择
100 0
|
6月前
|
存储 缓存 NoSQL
Redis之持久化(RDB和AOF)
Redis之持久化(RDB和AOF)
143 0
|
存储 缓存 NoSQL
【Redis 系列】redis 学习八,redis 持久化 RDB 和 AOF
【Redis 系列】redis 学习八,redis 持久化 RDB 和 AOF
|
3月前
|
缓存 NoSQL Redis
redis数据持久化之RDB和AOF
redis数据持久化之RDB和AOF
下一篇
无影云桌面