AOF日志
AOF(Append Only File)持久化功能,记录写操作命令到日志文件中,读操作是不会被记录的。
在Redis中,AOF是默认关闭的,修改redis.conf
:
appendonly yes
appendfilename "appendonly.aof"
写入日志的操作是单线程的,在一个进程里面,不是异步的,Redis会在写完数据之后,写入日志。
这个方法是有风险的:
- Redis还没来得及记录日志,就宕机了。
- 写日志可能不会阻塞当前操作命令,但是可能会阻塞下一个操作命令。
所以,这和AOF写回磁盘的时机有关了。
三种写回策略
在redis.conf
中,配置appendfsync
:
Always
:总是,每次写操作命令执行成功之后,同步写入AOF日志到硬盘。Everysec
:每秒,每次写操作命令执行成功之后,把日志写入AOF缓冲区,然后每隔1s写回硬盘。No
:不由Redis控制写回时机,由操作系统控制。每次都将日志写入AOF文件的内核缓冲区,由操作系统决定何时写入磁盘。
AOF重写
AOF日志是一个文件,随着操作越来越多,文件大小会越来越大。
所以,Redis为了避免AOF日志过大,提供了AOF重写机制。就是会为当前Redis中的所有数据生成一条插入语句,记录到新的AOF文件中,等全部记录完毕,再用新的AOF文件替换现有的AOF文件。
AOF重写一般是后台子进程(bgrewriteaof)完成的。
RDB快照
RDB快照是Redis实现持久化的另外一个方案。
RDB快照记录的是内存里面实际的数据,而AOF是记录的操作指令。
因此在Redis恢复的时候,RDB快照更快一些。
Redis提供了两个生成RDB文件的命令:
save
:主线程执行bgsave
:后台线程执行
可以在配置文件里面设置每隔多久执行一次bgsave命令:
save 900 1
save 300 10
save 60 10000
实际执行的是bgsave。
意思是:
- 900s内,对数据进行了至少1次修改
- 300s内,对数据进行了至少10次修改
- 60s内,对数据进行了至少10000次修改
执行快照的时候,数据能被修改吗?
肯定是可以的。
Redis使用写时复制技术,在执行bgsave的时候,会先fork子进程,然后子进程和父进程共享一块内存区域,但是,如果父进程对这些共享数据中的某块数据进行写操作的时候,就复制一块数据副本,主线程会在这个数据副本进行修改操作。同时bgsave的子进程可以继续把原来的数据写到RDB文件中。
RDB和AOF合体
AOF在数据恢复的时候速度较低,而RDB丢失数据的概率更大。
如果两者结合,就是混合持久化:
aof-use-rdb-preamble yes
混合持久化是在AOF重写日志的时候。fork出来的子进程会将主线程共享的内存数据以RDB方式写入AOF文件,然后将AOF重写期间执行的操作命令写入重写缓存区里,然后再把重写缓冲区的命令写如到AOF文件,写入完成之后通知主进程将含有RDB信息和AOF信息的AOF文件替换成旧的AOF文件。
也就是说,使用了混合持久化,AOF文件的前半部分是RDB格式的全量数据,后半部分是AOF格式的增量数据,这里是Redis后台子进程重写AOF期间,主线程处理的操作命令。