目录
一、AOF是什么?
二、使用AOF
三、命令写入
四、重写机制
4.1 触发AOF
4.2 AOF执行流程
一、AOF是什么?
AOF是Append Only File,是Redis中实现持久化的一种方式。以独⽴⽇志的⽅式记录每次命令,重启时再重新执⾏ AOF ⽂件中的命令达到恢复数据的⽬的。AOF 的主要作⽤是解决了数据持久化的实时性,⽬前已经是 Redis 持久化的主流⽅式。
二、使用AOF
开启 AOF 功能需要设置配置:appendonly yes,默认不开启。AOF ⽂件名通过 appendfilename配置(默认是appendonly.aof)设置。保存⽬录同 RDB 持久化⽅式⼀致,通过 dir 配置指定。AOF 的⼯作流程操作:命令写⼊(append)、⽂件同步(sync)、⽂件重写(rewrite)、重启加载(load),如图所示
配置完之后需要重启Redis,然后就会发现有了aof的文件了
- AOF的执行方式不是直接将数据写入AOF文件中的,而是将所有的命令数据写入到一个aof_buf的缓冲区中,这个缓冲区是在内存中的。
- AOF缓冲区会根据对应的刷新策略向硬盘做同步操作
- 随着AOF文件越来越大,需要定期对AOF文件进行重写,达到压缩的目的
- 当Redis重启时可以通过加载AOF文件进行数据恢复
三、命令写入
对Redis执行操作,观察aof文件中存储的都是命令语句,并且是以特殊字符来分隔的
AOF是将用户输入的命令直接追加到缓冲区中的,以特定的字符分隔开。那么为什么要写入缓冲区而不是直接写入AOF文件呢?
数据每次写入AOF文件中是直接同步硬盘的,多次同步硬盘会增加IO次数,但是一次同步的过程中数据量多是不会对性能有很大的影响的。所以就有了这种先将数据写入缓存中,然后再由缓存一次将数据都写入AOF文件中的方式来减少IO的次数。
但是,如果写入缓冲区的数据长时间不同步到AOF文件中的话就会造成数据丢失的风险,所以Redis也提供了多种缓冲区的的同步策略,让用户根据自己的需求做出合理的调整。
- always:只要命令写入缓冲区就立刻同步到AOF文件中
- everysec(everysecond):每秒将缓冲区的命令同步一次到AOF文件中(Redis默认)
- no:不执行任何同步策略,由操作系统自行安排
四、重写机制
随着AOF文件中不断有命令写入,文件也会越来越大,为了解决这个问题,Redis引入了AOF重写机制来压缩文件的体积。AOF文件重写就是把Redis进程内的数据转化为写命令同步到新的AOF文件中。为什么重写可以使得AOF文件变小呢?
由于AOF文件中是存储Redis命令的,其中不乏有很多重复的命令,例如以下几种,都是对同一个key进行操作,最后的结果应该是 key = 3333 就行了,但是在AOF文件中存储的却是所有的命令,久而久之肯定就会造成文件空间过度浪费。所以这里就有了重写的机制
4.1 触发AOF
- bgrewriteaof (手动输命令触发)
创建一个子线程,在子线程中进行重写,最后将重写的AOF文件替换原有的文件
- 自动触发
根据auto-aof-rewrite-min-size和auto-aof-rewrite-percentage参数确定⾃动触发时机。
auto-aof-rewrite-percentage:代表当前 AOF 占⽤⼤⼩相⽐较上次重写时增加的⽐例
auto-aof-rewrite-min-size:表⽰触发重写时 AOF 的最⼩⽂件⼤⼩,默认为64MB。
4.2 AOF执行流程
AOF的执行流程相比于RDB来说是差不多的,只是多了一个实时性。这里可能有的同学就会问了,既然是一样的那我还要RDB干嘛?并不是所有的场景都需要实时存储,可能有些场景就需要RDB的定时存储。所以特定的场景选用特定的技术才是最合适的
1. 首先执行AOF重写请求,如果当前进程正在执⾏ AOF 重写,请求不执⾏。如果当前进程
正在执⾏ bgsave 操作,重写命令延迟到 bgsave 完成之后再执⾏
2. 父进程阻塞等待(很快单位以微秒记)执行fork,创建出子进程
3. 重写
3.1 当父进程fork之后,继续响应其他命令。所有修改操作写⼊ AOF 缓冲区并根据 appendfsync策略同步到硬盘,保证旧 AOF ⽂件机制正确
3.2 ⼦进程只有 fork 之前的所有内存信息,⽗进程中需要将 fork 之后这段时间的修改
操作写⼊ AOF 重写缓冲区中
4. ⼦进程根据内存快照,将命令合并到新的 AOF ⽂件中(这里就是压缩后的文件)
5. 子进程完成重写
5.1 新⽂件写⼊后,⼦进程发送信号给⽗进程
5.2 父进程将AOF重写缓存区内临时保存的新命令追加到新AOF文件中
5.3 用新的AOF文件替换旧的的AOF文件