Redis随笔(四)-AOF

一、简介

aof日志的全称是append only file,它是一个追加写入的日志文件。AOF文件是可识别的纯文本,它的内容就是一个个的Redis标准命令,可以直接使用vi查看。
redis默认使用RDB持久,开启AOF持久化:在redis.conf文件中设置appendonly为yes,如下所示:
开启aof
AOF文件是可识别的纯文本,它的内容就是一个个的Redis标准命令,可以直接使用vi查看:
这里写图片描述

二、AOF持久化过程

AOF持久化需要将所有写命令记录在文件中来保存服务器状态,而文件写入操作效率比较低,如果每执行一条写命令都要写一次AOF文件无疑是低效的。为了提高效率,Redis提供了一个中间层 – AOF缓冲区,也就是说当Redis执行一条写命令后,先将该命令追加到AOF缓冲区中,在以后的某个时刻再将AOF缓冲区中的内容同步到文件中。AOF缓冲区定义在redisServer结构体中,实际上是一个字符串对象。

AOF持久化功能的实现可以分为命令追加(append)、文件写入、文件同步三步。

  1. 命令追加:当打开aof持久化功能后,服务器执行一个写的命令后,会以协议的格式将被执行的写命令追加到服务器状态的aof_buf缓冲区末尾。
  2. 文件写入:redis的服务器进程就是一个事件循环,每次循环的时候都会把aof_buf缓冲区中的所有内容写到aof文件中。
  3. 文件同步:同步到磁盘,同步方式参照下面的文件同步策略。

三、文件同步策略

AOF文件同步策略可以在redis.conf文件中设置.。
文件同步策略
1. appednfsync always:当设置appendfsync为always时,每一次写操作都会调用一次fsync,这时数据是最安全的,当然,由于每次都会执行fsync,所以其性能也会受到影响。
2. appendfsync everysec:当设置appendfsync为everysec的时候,Redis会默认每隔一秒进行一次fsync调用,将缓冲区中的数据写到磁盘。但是当这一次的fsync调用时长超过1秒时。Redis会采取延迟fsync的策略,再等一秒钟。也就是在两秒后再进行fsync,这一次的fsync就不管会执行多长时间都会进行。这时候由于在fsync时文件描述符会被阻塞,所以当前的写操作就会阻塞。所以,结论就是,在绝大多数情况下,Redis会每隔一秒进行一次fsync。在最坏的情况下,两秒钟会进行一次fsync操作。这一操作在大多数数据库系统中被称为group commit,就是组合多次写操作的数据,一次性将日志写到磁盘。
3. appendfsync no:当设置appendfsync为no的时候,Redis不会主动调用fsync去将AOF日志内容同步到磁盘,所以这一切就完全依赖于操作系统的调试了。对大多数Linux操作系统,是每30秒进行一次fsync,将缓冲区中的数据写到磁盘上。

四、AOF重写

虽然redis将生成新的aof文件替换旧的aof文件的功能叫做“aof文件重写”,但是实际上aof文件重写并不需要对现有的aof文件进行任何读取、分析或者写入操作,这个功能是根据通过读取服务器当前数据库状态实现的。
aof重写
在实际中,为了避免在执行命令时造成客户端缓冲区溢出,重写程序在处理列表、哈希表、集合、有序集合这四种可能会带有多种元素的键时,会先检查所包含元素的数量,如果元素数量超过redis.h/REDIS_AOF_REWRITE_ITEMS_PER_CMD常量的值,那么重写程序将使用多条命令来记录键的值,而不是一条。REDIS_AOF_REWRITE_ITEMS_PER_CMD常量的值为64.

例如:一个集合键包含超过64个元素,那么重写程序会使用多条SADD命令来记录这个集合,每条命令记录64个元素

SADD <set-key> <elem1> <elem2> ... <elem64>
SADD <set-key> <elem65> <elem66> ... <elem128>
SADD <set-key> <elem129> <elem130> ... <elem192>
...

aof重写命令会进行大量写的操作,所以调用这个函数的线程会被长时间阻塞,而redis是单线程处理命令请求,如果由服务器直接调用这个函数的话,在aof重写期间,服务器将无法处理客户端请求,所以就把aof重写放到子进程中执行。

但是在子进程进行aof重写期间,服务器进程还需要继续处理命令请求,而新的命令可能会修改数据库状态,使当前数据库状态与重写后的aof文件保存的数据库状态不一致。

为了解决这个问题,redis服务器设置了一个aof重写缓冲区,这个缓冲区在服务器创建子进程后开始使用,当redis执行一个写命令后,服务器同样会把这个命令发送给aof缓冲区和aof重写缓冲区。aof缓冲区的内容会定期被写入和同步到aof文件,对现有的aof文件处理照常进行;重创建子进程开始,服务器执行所有写的命令都会被记录到aof重写缓冲区。

aof重写完成后,会向父进程发送一个信号父进程接收到该信号后,会将aof重写缓冲区中的内容写入新aof文件中,此时新aof文件中保存的数据库状态就与服务器状态一致了,对新aof文件改名,覆盖现有的aof文件,完成新旧aof文件替换。

猜你喜欢

转载自blog.csdn.net/qq_37502106/article/details/80165490