06.持久化-AOF
约 860 字大约 3 分钟...
写日志的方式:
WAL:写前日志(Write Ahead Log, WAL)在实际写数据前,先把修改的数据记到日志文件中,以便故障时进行恢复(mysql 先把数据写到redo log,再落盘)。
AOF:写后日志, Redis 是先执行命令,把数据写入内存,然后才记录日志。(所以AOF不是crash-safe的)
AOF:
- AOF 里记录的是 Redis 收到的
每一条写操作
。以文本形式保存的。 - 优点:
- AOF是
顺序写
,不需要检查和索引操作,避免了额外检查的开销 - 不会阻塞
当前
的写入操作
- AOF是
- 缺点:
- 未写入AOF的那部分数据可能会丢失
- 因为些操作和写AOF都是在主进程中,所以写AOF时,可能会阻塞后一个
写操作
- 刷盘时机:
配置
appendfsync
:- Always:每次执行命令后,通过系统调用fsync刷盘
- Everysec:创建异步,每隔1秒,调用一次fsync刷盘
- No:由操作系统控制,不主动调用fsync
图片
AOF 缓冲区
:- 将命令刷盘前,先放入 AOF 缓冲区,然后通过fsync刷盘。服务于AOF 文件刷盘,提高刷盘效率。
AOF 文件格式:
*3
$3
set
$4
name
$3
yhj
AOF 完整过程:

AOF 重写机制:
- 作用: 通过将原有AOF文件进行重写(单个键值的操作合并),从而
对AOF文件大小进行压缩
- 文件过大带来的问题:
- 文件系统本身的限制,无法保存过大的文件
- 文件太大,追加命令记录效率会变低
- 大文件恢复过程会非常缓慢
- 机制说明:
AOF 重写
发生时,原AOF操作依然在进行- 如何重写:根据Redis当前内存中,这个键值对当前的
最新状态
,生成对应的写入命令 - 重写过程是由后台子进程
bgrewriteaof
执行,不阻塞主进程
- 技术细节:
- 写时复制COW(copy on write):
- 通过fork,生成后台子进程
bgrewriteaof
- 这样后台子进程共享主进程的物理内存数据,不需要花费大量时间进行数据复制
- 子进程只会对该物理内存进行读取操作
- 主进程中因为不阻塞命令执行,会发生数据变更。此时操作系统会复制这些
变化的数据内存
,即写时复制
- 通过fork,生成后台子进程
- 数据一致性:
- 当数据出现变更时,主进程会把增量写命令写到
AOF 缓冲区
和AOF重写缓冲区
- 子进程AOF重写完成后,发送信号给主进程。
- 继续将
AOF重写缓冲区
数据写入AOF文件 - 替换AOF文件
- 当数据出现变更时,主进程会把增量写命令写到
- 主进程发生阻塞时机:
- 触发重写时,fork操作需要复制页表,如果页表比较大(比如开启
内存大页
4KB->1MB),会阻塞主进程 - 当发生写时复制,如果写入bigkey,会阻塞主进程(主要是又触发了内存分配)
- 触发重写时,fork操作需要复制页表,如果页表比较大(比如开启
AOF 重写缓冲区
:AOF 重写
过程中,增量的写命令
需要额外记录到AOF 重写缓冲区
,等重写完成,将其写入AOF文件。AOF 重写缓冲区
服务于AOF重写时的数据一致性。
- 写时复制COW(copy on write):
AOF 重写过程:
