文章目录

什么是AOF?
Redis AOF(Append-Only File)持久化是一种将每个写操作以追加的方式写入日志文件的机制,用于记录数据库的命令和数据修改操作。它可以保证数据在系统重启或崩溃后的持久化和恢复。将Redis内存中的数据持久化到磁盘中,一般用于系统重启或崩溃之后的数据恢复,为数据提供保障。
如何开启AOF/如何配置Redis使用AOF持久化?
AOF是默认开启的吗?
在Redis中,AOF(Append-Only File)持久化在默认情况下是关闭的。
开启Redis的AOF持久化步骤
- 打开Redis的配置文件(redis.conf):
$ sudo nano /path/to/redis.conf
- 在配置文件中找到以下行(可能在注释行中):
\# appendonly no
- 将该行的注释去掉,并将选项值从 “no” 改为 “yes”:
appendonly yes
- 保存配置文件并关闭编辑器。
- 重启Redis服务器,使配置生效。
AOF持久化基本流程
1、客户端发送命令,redis接收并进行写操作。
2、redis将写操作追加到AOF缓存区中,不会立即将其写入到AOF文件中。
3、将AOF缓存区中数据写入到AOF日志文件中(持久化到磁盘的时间是操作系统决定,我们只能决定什么时候进行写入)
为什么需要AOF缓存区?
- 提高性能:AOF缓冲区允许Redis将写操作首先写入内存中的缓冲区,而不是直接写入AOF文件。由于内存操作速度较快,将写操作暂时存储在AOF缓冲区中可以提高Redis的写入性能。
- 减少磁盘I/O:将写操作先写入AOF缓冲区,而不是直接写入AOF文件,可以减少磁盘I/O的频率。较少的磁盘写入操作可以降低磁盘的负载,提高整体系统性能。
- 批量写入:AOF缓冲区允许Redis将多个写操作合并为一个较大的写入操作。这样可以减少写入AOF文件的次数,提高写入效率。
- 减少AOF文件碎片:通过将多个写操作合并为一个写入操作,AOF缓冲区可以减少AOF文件的碎片化。碎片化的AOF文件可能会导致文件过大和读取性能下降,而AOF缓冲区可以一定程度上减轻这个问题。
- 容错能力:AOF缓冲区可以帮助Redis在发生故障或崩溃时提供一定的容错能力。即使Redis崩溃,AOF缓冲区中的写操作仍然存在,并可以用于恢复数据库状态
如何处理AOF文件过大的问题?
AOF的重写机制
如何/怎样触发AOF的重写机制?
1、通过手动的方式触发重写 bgrewriteaof
2、自动触发:Redis还提供了自动触发AOF重写的机制。可以通过以下两个配置选项来配置自动触发的条件:
- auto-aof-rewrite-percentage:指定AOF文件的大小相对于上一次重写时的大小增长百分比。当AOF文件的大小增长超过设定的百分比时,触发自动AOF重写。默认值为100(即AOF文件大小翻倍时触发)。
- auto-aof-rewrite-min-size:指定AOF文件的最小大小,以MB为单位。当AOF文件的大小超过设定的最小大小,并且增长超过auto-aof-rewrite-percentage所设定的百分比时,触发自动AOF重写。默认值为64MB。
主进程在子进程执行AOF重写期间
1、执行客户端发送过来的命令。
2、将命令追加到AOF缓存区。
3、将命令追加到AOF重写缓存区。
子进程重写操作过程:
AOF重写实际上是主进程fork()出一个重写子进程进行重写操作,实际重写操作过程如下:
1、主进程在通过fork系统调用生成 bgrewriteaof 子进程
2、子进程读取数据,这里会运用到我们上面所讲的压缩机制,对数据或命令进行重写。
3、将重写的aof文件替换掉原有的aof文件。
当子进程完成 AOF 重写工作(扫描数据库中所有数据,逐一把内存数据的键值对转换成一条命令,再将命令记录到重写日志)后,会向主进程发送一条信号,信号是进程间通讯的一种方式,且是异步的。
主进程收到该信号后,会调用一个信号处理函数,该函数主要做以下工作:
将 AOF 重写缓冲区中的所有内容追加到新的 AOF 的文件中,使得新旧两个 AOF 文件所保存的数据库状态一致;
新的 AOF 的文件进行改名,覆盖现有的 AOF 文件。
信号函数执行完后,主进程就可以继续像往常一样处理命令了。
压缩机制
1、第一种方式 直接根据Redis存储的数据进行反推存入到AOF重写缓存中
2、如果命令连续的话,会进行语义分析,对命令进行简化,例如:lpush hhk A B,lpush hhk C D,rpop hhk,rpop hhk只存lpush hhk C D
写时复制
写时复制通过共享物理内存的方式,提高读取效率。在进行重写的过程中,父子进程会共享物理内存,不过这个共享的内存只能以只读的方式。
主进程在通过 fork 系统调用生成 bgrewriteaof 子进程时,操作系统会把主进程的页表复制一份给子进程。两者的虚拟空间不同,但其对应的物理空间是同一个。(这样可以节约物理内存资源)
页表记录着虚拟地址和物理地址映射关系。当父进程或者子进程在向这个内存发起写操作时,会触发写时复制(注意这里只会复制主进程修改的物理内存数据,没修改物理内存还是与子进程共享的,复制物理内存数据时会阻塞父进程)
AOF重写缓存区的作用
子进程在重写过程,主进程也是在运行并且接收客户端的读写命令,会对缓存中的数据进行一些更新操作。当Redis主进程对内存中的数据A进行修改操作,假设数据A已经被子进程进行了重写,就会出现持久化的数据与内存数据不一致的情况,此时我们的AOF重写缓存区就出现了,它就是用来解决上述的问题。
AOF重写缓存区是在AOF重写过程中使用的临时存储区域,它不会持久化到磁盘上。一旦AOF重写完成,缓冲区中的数据就会被写入新生成的AOF文件,并替换原始的AOF文件。
问题:重写过程中,Redis既存放在【AOF缓冲区】又存放在【AOF重写缓冲区】,那么当子进程完成重写操作,并将重写缓冲区中的命令追加到AOF文件中,此时AOF缓冲区里面也有同样的命令,会不会造成重复插入?
在AOF重写完成后,Redis会继续正常地将写入命令追加到AOF缓冲区中,并将其写入新的AOF文件中。在这个过程中,Redis会确保不会出现重复的命令写入到AOF文件中。
Redis在AOF重写过程中会维护一个偏移量(offset),表示重写过程中已经处理的命令数量。当新的写入命令被追加到AOF缓冲区时,Redis会根据当前的偏移量,跳过已经在AOF重写缓冲区中的命令,以避免重复写入。
因此,尽管AOF缓冲区可能包含AOF重写缓冲区中的命令,Redis会通过偏移量来确保在下一次写入AOF文件时不会重复写入相同的命令。
需要注意的是,这种处理方式要求AOF重写过程完成后,新的写入命令必须与重写期间的命令相同。如果在AOF重写完成之前,Redis服务器重新启动或发生崩溃,AOF缓冲区中的新写入命令可能会被丢失。