AOF持久化配置
AOF持久化默认是关闭的;默认打开的是RDB的持久化。
生产环境里面AOF都是要打开的
appendonly yes
# appendfsync always
appendfsync everysec
# appendfsync no
打开AOF持久化机制之后,redis每次接收到一条写命令,就会写入日志文件中:先写入os cache的,然后每隔一定时间再fsync一下;
而且即使AOF和RDB都开启了,redis重启的时候,也是优先通过AOF进行数据恢复的,因为aof数据比较完整。
AOF的fsync策略有三种可以选择:
每次写入一条数据就执行一次fsync;
每隔一秒执行一次fsync;
一种是不主动执行fsync。
always: 每写入一条数据立即写日志fsync到磁盘上去,性能非常非常差,吞吐量很低;
everysec: 每秒将os cache中的数据fsync到磁盘,性能很高,QPS还是可以上万的;
no: 仅负责将数据写入os cache,os根据自己的策略将数据刷入磁盘。
mysql和redis对比(QPS):
mysql内存策略:大量磁盘,QPS到一两千;
redis基于内存: 磁盘持久化,QPS到多少上万。
AOF持久化数据恢复
修改配置:打开AOF的开关
appendonly yes
重启
redis-cli SHUTDOWN
./redis_6379 start
写入一些数据,观察AOF文件中的日志内容
root@VM-0-10-ubuntu:/etc/init.d# redis-cli
127.0.0.1:6379> set myhello aaa
OK
ls /var/redis/6379/
appendonly.aof dump.rdb
root@VM-0-10-ubuntu:/etc/init.d# cat /var/redis/6379/appendonly.aof
*2
$6
SELECT
$1
0
*3
$3
set
$7
myhello
$3
aaa
在appendonly.aof文件中,可以看到刚写的日志。其实是先写入os cache的,然后1秒后才fsync到磁盘中。
-kill -9杀掉redis进程,重新启动redis进程
root@VM-0-10-ubuntu:/etc/init.d# ps -ef|grep redis
root 10302 1 0 18:34 ? 00:00:00 /usr/local/bin/redis-server 127.0.0.1:6379
root 11164 8229 0 18:40 pts/0 00:00:00 grep --color=auto redis
root@VM-0-10-ubuntu:/etc/init.d# kill -9 10302
root@VM-0-10-ubuntu:/etc/init.d# ./redis_6379 start
/var/run/redis_6379.pid exists, process is already running or crashed
root@VM-0-10-ubuntu:/etc/init.d# rm -rf /var/run/redis_6379.pid
root@VM-0-10-ubuntu:/etc/init.d# ./redis_6379 start
root@VM-0-10-ubuntu:/etc/init.d# redis-cli
127.0.0.1:6379> get myhello
"aaa"
127.0.0.1:6379> get k1
(nil)
发现数据被恢复了,但是之前保存在RDB里的数据没有了。
这也说明了redis启动的时候,直接从appendonly.aof中加载所有的日志来恢复数据。
AOF rewrite
redis中的数据其实有限的,很多数据可能会自动过期。
AOF会自动在后台每隔一定时间做rewrite操作, 确保AOF日志文件不会过大,保持跟redis内存数据量一致。目前redis会自动进行rewrite操作。
通过在redis.conf中配置rewrite策略:
auto-aof-rewrite-percentage 100
auto-aof-rewrite-min-size 64mb
比如说上一次AOF rewrite 是100mb,然后就会接着100mb继续写AOF的日志,如果发现增长的比例,超过了之前的100% 也就是200mb,就可能会去触发一次rewrite;
但是此时还要去跟min-size,64mb去比较,200mb > 64mb,才会去触发rewrite。
fork子进程,基于当前内存中的数据,往一个新的临时的AOF文件中写入日志;
redis主进程在接收到新的写操作之后,在内存中写入日志,同时也继续写入旧的AOF文件
子进程写完新的日志文件之后,redis主进程将内存中的新日志再次追加到新的AOF文件中
用新的日志文件替换掉旧的日志文件
AOF破损文件的修复
如果redis在append数据到AOF文件时,机器宕机会导致AOF文件损坏。如将appendonly.aof删掉最后一行来模拟宕机:
root@VM-0-10-ubuntu:~# vi /var/redis/6379/appendonly.aof
*2
$6
SELECT
$1
0
*3
$3
set
$7
myhello
$3
用redis-check-aof --fix命令来修复AOF文件:
root@VM-0-10-ubuntu:~/redis/redis-4.0.9/src# ./redis-check-aof --fix /var/redis/6379/appendonly.aof
0x 35: Expected to read 5 bytes, got 0 bytes
AOF analyzed: size=53, ok_up_to=23, diff=30
This will shrink the AOF from 53 bytes, with 30 bytes, to 23 bytes
Continue? [y/N]: y
Successfully truncated AOF
cat /var/redis/6379/appendonly.aof
*2
$6
SELECT
$1
0
AOF和RDB同时工作
1.如果RDB执行snapshotting,那么redis就不会再去执行AOF rewrite。反之,如果redis在执行AOF rewrite,那么也不会执行RDB snapshotting;
2.如果RDB执行snapshotting,此时用户也在执行BGREWRITEAOF命令,那么只有等RDB快照生成之后,才会执行AOF rewrite;
3.如果同时拥有RDB snapshot文件和AOF日志文件,那么redis重启的时候会优先使用AOF进行恢复,因为其日志更完整。
总结
同时有rdb的dump和aof的appendonly,优先使用AOF进行恢复,rdb的数据不会恢复到内存中
模拟aof破损,然后通过命令fix,破损的数据会被删除
数据恢复完全依赖于磁盘持久化,如果rdb和aof上都没有数据,数据就无法恢复了。