在 Redis 中 AOF 持久化功能默认是不开启的,需要我们修改 redis.conf
配置文件中的以下参数:
Redis 是先执行写操作命令后,才将该命令记录到 AOF 日志里的 :
优点:先执行写操作命令再记录日志的话,只有在该命令执行成功后,才将命令记录到 AOF 日志里,这样就不用额外的检查开销,不会出现语法错误等问题,保证记录在 AOF 日志里的命令都是可执行并且正确的
缺点:执行写操作命令和记录日志是两个过程,那当 Redis 在还没来得及将命令写入到硬盘时,服务器发生宕机了,这个数据就会有丢失的风险
server.aof_buf
缓冲区; redis.conf
配置文件中的 appendfsync
配置项可以有以下 3 种参数可填:
Always 策略的性能比较差,可靠性高,尽可能保证数据不会丢失
Everysec策略性能适中,宕机会丢失一秒的数据
No策略性能良好,宕机会丢失较多的数据
AOF 日志是一个文件,随着执行的写操作命令越来越多,文件的大小会越来越大。
其中AOF日志中
Redis 为了避免 AOF 文件越写越大,提供了 AOF 重写机制,当 AOF 文件的大小 超过所设定的阈值后,Redis 就会启用 AOF 重写机制,来压缩 AOF 文 件。
AOF重写机制
读取当前数据库中的所有键值对,然后将每一个键值对用一条命令记录到「新的 AOF 文件」
作用:
为什么重写 AOF 的时候,不直接复用现有的 AOF 文件,而是先写到新的 AOF 文件再覆盖过去?
如果 AOF 重写过程中失败了,现有的 AOF 文件就会造成污染,可能无法用于恢复使用。
当 触发 AOF 重写时,比如当 AOF 文件大于 64M 时,就会对 AOF 文件进行重写,这时是需要读取所有缓存的键值对数据,并为每个键值对生成一条命令,然后将其写入到新的 AOF 文件,重写完后,就把现在的 AOF 文件替换掉。这个过程其实是很耗时的,所以重写的操作不能放在主进程
所以,Redis 的 重写 AOF 过程是由后台子进程 bgrewriteaof 来完成的,这样做有两个作用:
子进程是怎么拥有主进程一样的数据副本的呢?
当父进程 使用fork 创建子进程的时候,会将父进程中的页表 复制给子进程,因此父子进程它们的共享一块物理内存。
写时复制顾名思义,在发生写操作的时候,操作系统才会去复制物理内存,这样是为了防止 fork 创建子进程时,由于物理内存数据的复制时间过长而导致父进程长时间阻塞的问题。
重写子进程只会对这个内存进行只读,重写 AOF 子进程会读取数据库里的所有数据,并逐一把内存数据的键值对转换成一条命令,再将命令记录到重写日志(新的 AOF 文件)
重写 AOF 日志过程中,如果主进程修改了已经存在 key-value,此时这个 key-value 数据在子进程的内存数据就跟主进程的内存数据不一致了,这时要怎么办呢?
Redis 设置了一个 AOF 重写缓冲区,这个缓冲区在创建 bgrewriteaof 子进程之后开始使用
在重写 AOF 期间,当 Redis 执行完一个写命令之后,它会同时将这个写命令写入到 「AOF 缓冲区」和 「AOF 重写缓冲区」。
当子进程完成 AOF 重写工作(扫描数据库中所有数据,逐一把内存数据的键值对转换成一条命令,再将命令记录到重写日志)后,会向主进程发送一条信号。
主进程收到该信号后,会调用一个信号处理函数,该函数主要做以下工作: