文章内容是学习过程中的知识总结,如有纰漏,欢迎指正
文章目录
前言
Redis是内存数据库,数据都是存储在内存中,为了避免进程退出导致数据的永久丢失,需要定期将Redis中的数据以某种形式(数据或命令)从内存保存到硬盘;当下次Redis重启时,利用持久化文件实现数据恢复。除此之外,为了进行灾难备份,可以将持久化文件拷贝到一个远程位置,redis提供了两种不同的持久化方式:RDB(Redis DataBase)和AOF(Append Only File),今天我们一起来学习AOF。关于RDB可以看另外一篇文章[博学谷学习记录]超强总结,用心分享|架构 Redis持久化原理之RDB_code只是爱好的博客-CSDN博客
以下是本篇文章正文内容
一、AOF是什么?
- AOF(append only file):记录每次对服务器写的操作(命令),当服务器重启的时候会重新执行这些命令来恢复原始的数据。(默认不开启)
AOF特点:
1. 以日志的形式来记录用户请求的写操作,读操作不会记录,因为写操作才会存储2. 文件以追加的形式而不是修改的形式3. redis的aof恢复其实就是把追加的文件从开始到结尾读取 执行 写操作
二、AOF 持久化的实现
如上图所示,AOF 持久化功能的实现可以分为命令追加( append )、文件写入( write )、文件同步( sync )、文件重写(rewrite)和重启加载(load)。其流程如下:
- 所有的写命令会追加到 AOF 缓冲中。
- AOF 缓冲区根据对应的策略向硬盘进行同步操作。
- 随着 AOF 文件越来越大,需要定期对 AOF 文件进行重写,达到压缩的目的。
- 当 Redis 重启时,可以加载 AOF 文件进行数据恢复。
三、开启
# 可以通过修改redis.conf配置文件中的appendonly参数开启
appendonly yes
# AOF文件的保存位置和RDB文件的位置相同,都是通过dir参数设置的。
dir .
# 默认的文件名是appendonly.aof,可以通过appendfilename参数修改
appendfilename appendonly.aof
四、命令追加
当 AOF 持久化功能处于打开状态时,Redis 在执行完一个写命令之后,会以协议格式(也就是RESP,即 Redis 客户端和服务器交互的通信协议 )将被执行的写命令追加到 Redis 服务端维护的 AOF 缓冲区末尾。
比如说 SET mykey myvalue 这条命令就以如下格式记录到 AOF 缓冲中。
"*3\r\n$3\r\nSET\r\n$5\r\nmykey\r\n$7\r\nmyvalue\r\n"
Redis 协议格式本文不再赘述,AOF之所以直接采用文本协议格式,是因为所有写入命令都要进行追加操作,直接采用协议格式,避免了二次处理开销。
五、文件写入和同步(触发)
Redis 每次结束一个事件循环之前,它都会调用 flushAppendOnlyFile
函数,判断是否需要将 AOF 缓存区中的内容写入和同步到 AOF 文件中。
flushAppendOnlyFile
函数的行为由 redis.conf 配置中的 appendfsync
选项的值来决定。该选项有三个可选值,分别是 always
、 everysec
和 no
:
#appendfsync always
appendfsync everysec
#appendfsync no
always
:每执行一个命令保存一次 高消耗,最安全everysec
:每一秒钟保存一次no
:只写入 不保存, AOF 或 Redis 关闭时执行,由操作系统触发刷新文件到磁盘
写入和保存概念WRITE:根据条件,将 aof_buf 中的缓存写入到 AOF 文件。SAVE:根据条件,调用 fsync 或 fdatasync 函数,将 AOF 文件保存到磁盘中。
六、AOF 数据恢复
AOF 文件里边包含了重建 Redis 数据所需的所有写命令,所以 Redis 只要读入并重新执行一遍 AOF 文件里边保存的写命令,就可以还原 Redis 关闭之前的状态
Redis 读取 AOF 文件并且还原数据库状态的详细步骤如下:
- 创建一个不带网络连接的的伪客户端( fake client),因为 Redis 的命令只能在客户端上下文中执行,而载入 AOF 文件时所使用的的命令直接来源于 AOF 文件而不是网络连接,所以服务器使用了一个没有网络连接的伪客户端来执行 AOF 文件保存的写命令,伪客户端执行命令的效果和带网络连接的客户端执行命令的效果完全一样的。
- 从 AOF 文件中分析并取出一条写命令。
- 使用伪客户端执行被读出的写命令。
- 一直执行步骤 2 和步骤3,直到 AOF 文件中的所有写命令都被处理完毕为止。
当完成以上步骤之后,AOF 文件所保存的数据库状态就会被完整还原出来。
七、AOF "重写"
问题分析:AOF采用文件追加方式,随着Redis长时间运行,会产生什么问题?
为了解决 AOF 文件体积膨胀的问题,Redis 提供了 AOF 文件重写( rewrite) 策略
如上图所示,重写前要记录名为 list
的键的状态,AOF 文件要保存五条命令,而重写后,则只需要保存一条命令。
AOF 文件重写并不需要对现有的 AOF 文件进行任何读取、分析或者写入操作,而是通过读取服务器当前的数据库状态来实现的。首先从数据库中读取键现在的值,然后用一条命令去记录键值对,代替之前记录这个键值对的多条命令,这就是 AOF 重写功能的实现原理。
rewrite的触发机制主要有:
- 手动调用 bgrewriteaof 命令,如果当前有正在运行的 rewrite 子进程,则本次rewrite 会推迟执行,否则,直接触发一次 rewrite
- 自动触发 就是根据配置规则来触发
# 重写机制:避免文件越来越大,自动优化压缩指令,会fork一个新的进程去完成重写动作,新进程里的内存数据会被重写,此时旧的aof文件不会被读取使用# 当前AOF文件的大小是上次AOF大小的100% 并且文件体积达到64m,满足两者则触发重写auto-aof-rewrite-percentage 100auto-aof-rewrite-min-size 64mb
stat appendonly.aof 查看aof文件
八、AOF重写原理
AOF 重写函数会进行大量的写入操作,调用该函数的线程将被长时间阻塞,所以 Redis 在子进程中执行 AOF 重写操作。
在整个 AOF 后台重写过程中,只有信号处理函数执行时会对 Redis 主进程造成阻塞,在其他时候,AOF 后台重写都不会阻塞主进程。
总结
- 如果Redis中的数据并不是特别敏感或者可以通过其它方式重写生成数据,可以关闭持久化,如果丢失数据可以通过其它途径补回;
- 自己制定策略定期检查Redis的情况,然后可以手动触发备份、重写数据;
- 可以加入主从机器,利用一台从机器进行备份处理,其它机器正常响应客户端的命令;
- RDB持久化与AOF持久化可以同时存在,配合使用。