目录
1 使用AOF
流程
问题一:父进程在fork之后继续写旧AOF文件的意义
问题二:执行BGREWRITEAOF时的特殊情况处理
2 命令写入
3 文件同步
4 重写机制
工作流程:
触发条件
混合持久化
持久化 sum
AOF(Append Only File)持久化
AOF持久化机制 以独立日志的方式记录每次写命令,重启时再重新执行AOF文件中的命令达到恢复数据的目的。
AOF的主要作用是解决了数据持久化的 实时性 问题,目前已经是Redis持久化的主流方式。理解掌握好AOF持久化机制对我们兼顾数据安全性和性能非常有帮助。
1 使用AOF
AOF文件是一个文本文件,每次进行的操作都会被记录到这个文本文件中,通过一些特殊符号作为分隔符,来对命令的细节做出区分.
AOF一般默认是关闭状态,我们需要通过修改配置文件来开启AOF功能.重启Redis服务之后生效.
cd ect/redis nano redis.conf
文件名配置:通过appendfilename
配置项(默认是appendonly.aof
)来指定AOF文件名。
保存目录:与RDB持久化方式一致,通过dir
配置指定。
重启后测试结果
可以查看到
流程
AOF重写机制涉及 创建一个子进程 来进行重写工作,而父进程继续处理客户端请求。具体步骤如下:
- 子进程创建与数据获取:
-
- 父进程通过
fork
创建一个子进程。 - 子进程不关心旧AOF文件内容,仅基于内存中的当前数据状态生成新的AOF文件。
- 父进程通过
- 数据写入方式:
-
- 子进程以文本格式写入新AOF文件,类似于RDB快照生成但使用不同格式。
- 父子进程协作:
-
- 父进程继续接收命令,并将这些命令 写入缓冲区以及旧的AOF文件中,确保即使重写失败也能保持数据完整性。
- 在子进程完成新AOF文件的写入后,它会通知父进程。父进程随后将自
fork
以来收到的新命令从aof_rewrite_buf
缓冲区追加到新AOF文件中,然后替换旧文件。
问题一:父进程在fork之后继续写旧AOF文件的意义
问题描述:
在Redis中进行AOF(Append Only File)文件重写时,父进程在fork子进程之后,子进程开始写入新的AOF文件。随着时间推移,子进程很快会完成新AOF文件的写入。此时,父进程继续写入即将被替换的旧AOF文件是否还有必要?
回答:
有必要。我们需要考虑 极端情况,比如在AOF文件重写过程中,如果子进程或服务器意外挂掉,子进程的内存数据将丢失,导致新的AOF文件不完整。因此,父进程会继续写入旧的AOF文件,以确保数据的安全性。
问题二:执行
BGREWRITEAOF
时的特殊情况处理
问题描述:
- 如果在执行
BGREWRITEAOF
命令时,Redis已经在进行AOF重写,会发生什么? - 如果在执行
BGREWRITEAOF
命令时,Redis正在生成RDB快照文件,会发生什么?
回答:
- 如果Redis已经在进行AOF重写,那么执行
BGREWRITEAOF
命令时,不会再次进行AOF重写,系统会直接返回。 - 如果Redis正在生成RDB快照文件,执行
BGREWRITEAOF
命令时,AOF重写操作会等待,直到RDB快照生成完成后,再进行AOF重写。
优先级
如果Redis上同时存在AOF文件和RDB快照的时候,此时以AOF文件为主,RDB直接被忽略.
过程复述:
在子进程创建时,它继承了父进程当前的内存状态,但不知道fork之后的新请求对内存的修改。为此,父进程准备了一个aof_rewrite_buf缓冲区,用于存储fork之后接收到的数据。子进程完成AOF数据写入后,会通过信号通知父进程,父进程再将aof_rewrite_buf缓冲区的内容写入新的AOF文件中,之后新的AOF文件就可以替代旧的AOF文件了。
2 命令写入
AOF命令写入的内容直接为文本协议格式。例如set hello world
这条命令,在AOF缓冲区会追加如下文本:
*3\r\n$3\r\nset\r\n$5\r\nhello\r\n$5\r\nworld\r\n
Redis选择文本协议的原因包括兼容性、实现简单和具备可读性。使用aof_buf
这个缓冲区, 使AOF机制在备份数据的时候, 不是直接让工作线程写入硬盘,而是先写入一个内存中的缓存区,积累一波之后,再统一写入硬盘.可以有效减少IO次数,并允许用户根据需求选择不同的同步策略,从而在性能和安全性之间做出平衡。
3 文件同步
AOF每次把新的操作写入到原有文件的末尾,属于顺序写入.而顺序写入的速度是比较快的.正是由于上面的两点,使得AOF虽然既要写内存又要写硬盘,但是他的效率没有降低多少.
但是如果把数据写在缓冲区的时候,本质上还是写在缓存中的,如果注解突然掉电或者进程崩溃,缓冲区的数据就会丢失.这时候,Redis就给出了一些同步硬盘中AOF文件的频率选项,也就是更新缓冲区数据的频率选项.
Redis提供了多种AOF缓冲区同步文件策略,由参数appendfsync
控制:
可配置值 | 说明 |
| 命令写入 |
| 每秒由后台线程调用 |
| 不主动调用 |
系统调用write
和fsync
的区别在于,
write
操作触发延迟写机制,而fsync
强制同步到磁盘。
刷新频率越高,性能影响越大,同时数据的可靠性越高,刷新频率越低,性能影响越小,数据的可靠性越低.
always
配置虽然最安全但性能差;no
配置提高了性能但增加了数据丢失的风险;everysec
是默认且推荐的配置,它能在数据安全性和性能间取得较好的平衡。
缓冲区刷新率也可以在配置文件中进行配置.具体的配置项是 appendfsync
,程序员可以根据自己的需要进行更改.
4 重写机制
随着AOF(Append Only File)文件体积的持续增长,文件会越来越大,这会影响到Redis下次启动时的启动时间。
- 因为Redis在启动时需要读取AOF文件的内容,而AOF记录的是操作Redis的中间过程。
- 实际上,Redis重启时关注的是 最终的数据状态。
- 为了优化这一过程,AOF可以通过 剔除冗余操作和合并操作 来减少文件大小,这就是AOF的重写机制。
示例1:
- 原始操作:
lpush key 111
和lpush key 222
- 优化后:
lpush key 111 222
示例2:
- 原始操作:
set key 111
和set key 222
- 优化后:只保留最后一个设置操作
set key 222
工作流程:
- 命令写入(append):所有写入命令追加到
aof_buf
(缓冲区)中。 - 文件同步(sync):根据配置的策略向硬盘同步AOF缓冲区内容。
- 文件重写(rewrite):定期对AOF文件进行重写以压缩其体积。
- 重启加载(load):服务器启动时加载AOF文件恢复数据。
触发条件
- 手动触发:可以调用
bgrewriteaof
指令来触发AOF重写。 - 自动触发:依据配置参数
auto-aof-rewrite-min-size
和auto-aof-rewrite-percentage
确定自动触发时机,前者表示AOF文件相对于上次重写时 增加的比例,后者表示触发 重写的最小文件大小。
混合持久化
为了解决纯文本写入的成本问题,Redis引入了混合持久化模式,结合了RDB和AOF的优点。
通过配置项aof-use-rdb-preamble
激活此功能后,Redis会在AOF重写时先以RDB二进制格式保存当前内存状态,之后的操作则继续以AOF文本格式追加到文件后面,重写时为 RDB 格式。
这种策略减少了写入成本,同时保持了AOF的实时性。
持久化 sum
- Redis提供了两种持久化方案:RDB和AOF。
- RDB视为内存快照,产生的内容紧凑,恢复速度快,但不适合实时持久化,通常用于冷备和主从复制。
- AOF视为修改命令的保存,并通过 重写机制定期压缩AOF文件。
- RDB和AOF都利用Linux 子进程拥有父进程 内存快照 的特点进行持久化,尽量不影响主进程处理命令。