Redis持久化——AOF机制详解

本文涉及的产品
云数据库 Redis 版,社区版 2GB
推荐场景:
搭建游戏排行榜
简介: 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
相关文章
|
1月前
|
存储 缓存 NoSQL
【Redis】Redis魔法:揭秘Key的自动消失术——过期删除机制解析
【Redis】Redis魔法:揭秘Key的自动消失术——过期删除机制解析
131 0
|
7天前
|
存储 NoSQL Java
Redis奔溃了快看看有没开启持久化
Reis作为一个内存数据库,整个数据库状态都存储在内存里,如果在运行过程中发生崩溃,那整个数据库状态可就完全不见了,相当于整个服务器被初始化。Redis在这方面肯定有所作为,我们来看看它做了什么功夫~
121 0
Redis奔溃了快看看有没开启持久化
|
18天前
|
存储 NoSQL 算法
redis数据持久化
redis数据持久化
|
28天前
|
NoSQL Java Redis
【Redis深度专题】「踩坑技术提升」一文教会你如何在支持Redis在低版本Jedis情况下兼容Redis的ACL机制
【Redis深度专题】「踩坑技术提升」一文教会你如何在支持Redis在低版本Jedis情况下兼容Redis的ACL机制
233 0
|
28天前
|
缓存 NoSQL Shell
【Redis深度专题】「核心技术提升」探究Redis服务启动的过程机制的技术原理和流程分析的指南(持久化功能分析)
【Redis深度专题】「核心技术提升」探究Redis服务启动的过程机制的技术原理和流程分析的指南(持久化功能分析)
158 0
|
28天前
|
存储 缓存 NoSQL
【Redis深度专题】「核心技术提升」探究Redis服务启动的过程机制的技术原理和流程分析的指南(集群功能分析)(一)
【Redis深度专题】「核心技术提升」探究Redis服务启动的过程机制的技术原理和流程分析的指南(集群功能分析)
345 0
|
1月前
|
NoSQL 应用服务中间件 Linux
Redis的内存回收机制
Redis的内存回收机制
25 2
|
1月前
|
缓存 NoSQL Redis
[Redis]——Redis持久化的两种方式RDB、AOF
[Redis]——Redis持久化的两种方式RDB、AOF
|
1月前
|
NoSQL 算法 数据管理
【Redis】Redis配置参数详解:优化过期删除机制
【Redis】Redis配置参数详解:优化过期删除机制
79 0
|
1月前
|
NoSQL 关系型数据库 MySQL
Redis 两种持久化方式 AOF 和 RDB
Redis 两种持久化方式 AOF 和 RDB

热门文章

最新文章