AOF日志如何实现
- 对比:
1. 数据库一般是写前日志(WAL,write ahead log),在实际写数据前,先把修改的数据记到日志文件
2. AOF是Redis先执行命令,把数据写入内存,然后再记录日志
- 为什么写后
1. AOF记录的是Redis收到的每一条命令,以文本形式保存,为了避免额外开销,redis在向AOF记录日志的时候,不会先对命令进行语法检查(先记日志,会出错)
2. 命令执行后才记录日志,不会阻塞当前的写操作
-
两个潜在风险
- 刚执行完一个命令,还没来得及记日志就宕机了
- 避免了对当前命令的阻塞,但可能给下一个操作带来阻塞(因为AOF日志也是在主线程执行,如果磁盘写压力大,就会写盘很慢,阻塞后续操作)
控制风险的三种写回策略
- Always:同步写回:每个写命令执行完,立马同步将日志写回磁盘
- Everysec:每秒写回:每个写命令执行完,先把日志写到AOF文件内存缓冲区,每隔1s把缓冲区内容写入磁盘
- No:操作系统控制写回:每个写命令执行完,先把日志写到AOF文件内存缓冲区,由操作系统决定何时将缓冲区写回磁盘
三种策略的优缺点

- 高性能:No
- 高可靠:Always
- 取中:Everysec
性能问题
- 文件系统本身对文件大小的限制
- 文件过大,追加命令会效率较低
- 如果宕机,文件大,恢复会很慢
控制文件大小的手段:AOF重写机制
- 多变一功能,当一个键值对被多条写命令反复修改时,AOF文件会记录相应多条命令,但,重写,是根据这个键值对当前最新状态来写入
- 问题:重写会不会阻塞主线程
重写原理:一个拷贝,两处日志
- AOF日志由主线程写回,重写过程由后台线程bgrewriteaof来完成(原因就是为了避免阻塞主线程)
- 一个拷贝,两处日志
-
一个拷贝:每次执行重写时,主线程 fork 出后台的 bgrewriteaof 子进程。此时,fork 会把主线程的内存拷贝一份给 bgrewriteaof 子进程,这里面就包含了数据库的最新数据。然后,bgrewriteaof 子进程就可以在不影响主线程的情况下,逐一把拷贝的数据写成操作,记入重写日志。
-
两处日志:
- 第一处日志:正在使用的AOF日志:因为主线程未阻塞,仍然可以处理新来的操作。此时,如果有写操作,第一处日志就是指正在使用的 AOF 日志,Redis 会把这个操作写到它的缓冲区。这样一来,即使宕机了,这个 AOF 日志的操作仍然是齐全的,可以用于恢复。
- 第二处日志:新的AOF重写日志,这个操作也会被写到重写日志的缓冲区
-

网友评论