AOF日志如何实现?
AOF(append only file)是写后日志,意思为Redis是先执行命令,把数据写入内存,然后才记录日志。
AOF中记录的是Redis收到的每一条命令,这些命令是以文本的形式保存下来。
“set testkey testvalue"命令后记录的日志为例,AOF内容为
*3
$3
set
$7
testkey
$9
testvalue解释:其中*3表明有三部分,每部分由”$+数字"开头,后面紧跟具体的命令、键或值
“$3 set"表明这部分有3个字节,也就是"set"命令
AOF的好处
- AOF是写后日志,可以避免出现记录错误命令的情况(写后,表明现在系统已经执行命令成功了)
- 命令执行后才记录日志,不会阻塞当前的写操作
AOF潜在风险
- 还没来的及写入日志就宕机了,这是无法用日志进行恢复(这里是使用redis当数据库,而不是作为mysql的缓存)
- AOF写会磁盘,会对下一个操作阻塞带来风险(AOF是在主线程中执行的,如果日志文件写入磁盘时,磁盘写压力大,就会导致写盘很慢,后续操作无法进行)
三种写回策略——写回磁盘
- ALways,同步写回:每个写命令执行完,立马同步地将日志写回磁盘
- Everysec,每秒写回:每个写命令执行完,只是先把日志写到AOF文件的内存缓冲区,每隔一秒把缓冲区的内容写入到磁盘
- No,操作系统控制写回:每个写命令执行完,只是先把日志写到AOF文件的内存缓冲区,由操作系统决定何时将缓冲区内容写回磁盘
总结一下:想要获得高性能,就选择No策略;如果想要保证高可靠性保证,就选择Always策略;如果允许数据有一点丢失,又希望性能别受太大影响的话,那么就选择Everysec策略。
AOF文件过大带来的性能问题
- 文件系统本身对文件大小有限制,无法保存过大的文件
- 如果文件太大,之后再往里面追加命令记录的话,效率也会变低
- 如果发生宕机,AOF中记录的命令要被一个个重新执行,用于故障恢复,如果文件过大,会导致恢复过慢,影响redis的正常使用
采用AOF重写来解决AOF过大带来的问题
AOF重写
- 多条命令变为一条(旧日志文件中的多条命令,在重写后的新日志中变成了一条命令)
- 在重写的时候,是根据这个键值对当前的最新状态,为它生成对应的写入命令。(具体看图片)
进一步思考
AOF重写会阻塞吗
重写过程是由后台线程bgrewriteaof来完成的,这也是为了避免阻塞主线程,导致数据库性能下降- ”一个拷贝“
- 每次执行重写时,主线程fork()出后台到的bgrewriteaof子进程。此时,fork会把主线程的内存拷贝一份给bgrewriteaof子进程
- ”两处日志“
- 因为主线程未阻塞,仍然可以处理新来的操作。第一处日志就是指正在使用的AOF日志,Redis会把这个操作写到他的缓冲区。这样一来,即使宕机了,这个AOF日志的操作仍然是齐全的,可以用于恢复
- 第二处日志,就是指的新的AOF重写日志。这个操作也会被写到AOF重写缓冲,这样重写日志才不会丢失最新的操作。完成之后就可以用新的AOF来替代旧的AOF了。