前言✍
可以先看往期的 【RDB🔍】
快照功能(RDB)并不是非常耐久(durable): 如果 Redis 因为某些原因而造成故障停机, 那么服务器将丢失最近写入、以及未保存到快照中的那些数据。 从 1.1 版本开始, Redis 增加了一种完全耐久的持久化方式: AOF 持久化。
什么是AOF
AOF,英文是Append Only File,即只允许追加不允许改写的文件(修改aof会导致错误需要恢复,重启
)
如果要使用AOF,需要修改配置文件:
appendonly no yes则表示启用AOF
默认是不开启的,我们需要手动配置,然后重启redis,就可以生效了!
将我们的命令都记录下来,history,恢复的时候就把文件全部执行一遍!
👇来着(配置文件redis.conf
)
除了这些还有
#appendfsync always # 每次修改都会sync,消耗性能
#appendfsync everysec # 每秒执行一次sync,可能丢失这1s数据!
#appendfsync no #不执行sync,这个时候操作系统自己同步数据,速度最快!
auto-aof-rewrite-percentage 100
auto-aof-rewrite-min-size 64mb
# aof默认就是文件的无限追加,越来越大
# 如果aof文件大于64mb
#frok一个新的的进程来将我们的文件进行重写!
appendonly
appendonly默认是不开启的,需要手动进行配置
1.首先开启两个会话👇
连接会话1 20001107
2.打开redis.conf
把的no改为yes就可以了(开启aof
)
这时我们还没有重启redis
我们看到bin目录下没有aof文件
[root@GongQlLong bin]# ls
dump.rdb
redis-benchmark
redis-check-rdb redis.conf
redis-server
gongconfig
redis-check-aof
redis-cli
redis-sentinel
删除dump.rdb文件
[root@GongQlLong bin]# ls
dump.rdb
redis-benchmark
redis-check-rdb
redis.conf
redis-server
gongconfig
redis-check-aof
redis-cli
redis-sentinel
[root@GongQlLong bin]# rm -rf dump.rdb
连接会话2 20001107
3.重启redis
[root@GongQlLong bin]# redis-server gongconfig/redis.conf
27564:C 05 Dec 2021 16:44:50.933 # oO0OoO0OoO0Oo Redis is starting oO0OoO0OoO0Oo
27564:C 05 Dec 2021 16:44:50.933 # Redis version=5.0.14, bits=64, commit=00000000, modified=0, pid=27564, just started
27564:C 05 Dec 2021 16:44:50.933 # Configuration loaded
[root@GongQlLong bin]# redis-cli
127.0.0.1:6379> ping
OK
连接会话1 20001107
4.查看bin目录
[root@GongQlLong bin]# ls
appendonly.aof
gongconfig
redis-check-aof
redis-cli
redis-sentinel
dump.rdb
redis-benchmark
redis-check-rdb
redis.conf
redis
出现了appendonly.aof
也有了dump.rdb
Aof保存的是appendonly.aof文件
AOF命令同步
AOF 命令同步
Redis 将所有对数据库进行过写入的命令(及其参数)记录到 AOF 文件, 以此达到记录数据库状态的目的, 为了方便起见, 我们称呼这种记录过程为同步。
举个例子, 如果执行以下命令:
redis> RPUSH list 1 2 3 4
(integer) 4
redis> LRANGE list 0 -1
1) "1"
2) "2"
3) "3"
4) "4"
redis> KEYS *
1) "list"
redis> RPOP list
"4"
redis> LPOP list
"1"
redis> LPUSH list 1
(integer) 3
redis> LRANGE list 0 -1
1) "1"
2) "2"
3) "3"
那么其中四条对数据库有修改的写入命令就会被同步到 AOF 文件中:
RPUSH list 1 2 3 4
RPOP list
LPOP list
LPUSH list 1
为了处理的方便, AOF 文件使用网络通讯协议的格式来保存这些命令。
比如说, 上面列举的四个命令在 AOF 文件中就实际保存如下:
*2
$6
SELECT
$1
0
*6
$5
RPUSH
$4
list
$1
1
$1
2
$1
3
$1
4
*2
$4
RPOP
$4
list
*2
$4
LPOP
$4
list
*3
$5
LPUSH
$4
list
$1
1
如果这个aof文件有错位(比如你打开这个文件
(vim appendonly.aof然后修改保存过的值
)比如上面保存过的aof文件,把它修改一下
*2
$6
SELECT
$1
0
*6
$5
RPUSH
$4
list
$1
1
$1
2
$1
3
$1
4
*2
$4
RPOP
$4
list
*2
$4
LPOP
$4
list
*3
$5
LPUSH
$4
list
$1
adsddsadad sadas # 这是修改后的
这时候redis是启动不起来的,想要运行起来redis,需要修改这个恢复文件!!!!
恢复文件
redis给我们提供了一个工具redis-check-aof --fix
AOF 后台重写
AOF 重写程序可以很好地完成创建一个新 AOF 文件的任务, 但是, 在执行这个程序的时候, 调用者线程会被阻塞。
很明显, 作为一种辅佐性的维护手段, Redis 不希望 AOF 重写造成服务器无法处理请求, 所以 Redis 决定将 AOF 重写程序放到(后台)子进程里执行, 这样处理的最大好处是:
- 子进程进行 AOF 重写期间,主进程可以继续处理命令请求。
- 子进程带有主进程的数据副本,使用子进程而不是线程,可以在避免锁的情况下,保证数据的安全性。
不过, 使用子进程也有一个问题需要解决: 因为子进程在进行 AOF 重写期间, 主进程还需要继续处理命令, 而新的命令可能对现有的数据进行修改, 这会让当前数据库的数据和重写后的 AOF 文件中的数据不一致。
为了解决这个问题, Redis 增加了一个 AOF 重写缓存, 这个缓存在 fork 出子进程之后开始启用, Redis 主进程在接到新的写命令之后, 除了会将这个写命令的协议内容追加到现有的 AOF 文件之外, 还会追加到这个缓存中:
换言之, 当子进程在执行 AOF 重写时, 主进程需要执行以下三个工作:
处理命令请求。
将写命令追加到现有的 AOF 文件中。
将写命令追加到 AOF 重写缓存中。
这样一来可以保证:
现有的 AOF 功能会继续执行,即使在 AOF 重写期间发生停机,也不会有任何数据丢失。
所有对数据库进行修改的命令都会被记录到 AOF 重写缓存中。
当子进程完成 AOF 重写之后, 它会向父进程发送一个完成信号, 父进程在接到完成信号之后, 会调用一个信号处理函数, 并完成以下工作:
将 AOF 重写缓存中的内容全部写入到新 AOF 文件中。
对新的 AOF 文件进行改名,覆盖原有的 AOF 文件。
当步骤 1 执行完毕之后, 现有 AOF 文件、新 AOF 文件和数据库三者的状态就完全一致了。
当步骤 2 执行完毕之后, 程序就完成了新旧两个 AOF 文件的交替。
这个信号处理函数执行完毕之后, 主进程就可以继续像往常一样接受命令请求了。 在整个 AOF 后台重写过程中, 只有最后的写入缓存和改名操作会造成主进程阻塞, 在其他时候, AOF 后台重写都不会对主进程造成阻塞, 这将 AOF 重写对性能造成的影响降到了最低。
以上就是 AOF 后台重写
优点
- 每一次修改都同步,文件的完整会更加好!
- 每秒同步一次,可能会丢失一秒的数据
- 从不同步,效率最高的
缺点
- 相对于数据文件来说,aof远远大于rdb,修改的速度也比rdb慢
- Aof运行速率也要比rdb慢,说一我们redis默认的配置就是rdb持久化
扩展与总结
-
AOF方式是将执行过的写指令记录下来,在数据恢复时按照从前到后的顺序再将指令都执行一遍,就这么简单。
-
我们通过配置redis.conf中的appendonly yes就可以打开AOF功能。如果有写操作(如SET等),redis就会被追加到AOF文件的末尾。
-
默认的AOF持久化策略是每秒钟fsync一次(fsync是指把缓存中的写指令记录到磁盘中),因为在这种情况下,redis仍然可以保持很好的处理性能,即使redis故障,也只会丢失最近1秒钟的数据。
-
如果在追加日志时,恰好遇到磁盘空间满、inode满或断电等情况导致日志写入不完整,也没有关系,redis提供了redis-check-aof工具,可以用来进行日志修复。
-
因为采用了追加方式,如果不做任何处理的话,AOF文件会变得越来越大,为此,redis提供了AOF文件重写(rewrite)机制,即当AOF文件的大小超过所设定的阈值时,redis就会启动AOF文件的内容压缩,只保留可以恢复数据的最小指令集。举个例子或许更形象,假如我们调用了100次INCR指令,在AOF文件中就要存储100条指令,但这明显是很低效的,完全可以把这100条指令合并成一条SET指令,这就是重写机制的原理。
-
在进行AOF重写时,仍然是采用先写临时文件,全部完成后再替换的流程,所以断电、磁盘满等问题都不会影响AOF文件的可用性
-
AOF方式的另一个好处,我们通过一个“场景再现”来说明。某同学在操作redis时,不小心执行了FLUSHALL,导致redis内存中的数据全部被清空了,这是很悲剧的事情。不过这也不是世界末日,只要redis配置了AOF持久化方式,且AOF文件还没有被重写(rewrite),我们就可以用最快的速度暂停redis并编辑AOF文件,将最后一行的FLUSHALL命令删除,然后重启redis,就可以恢复redis的所有数据到FLUSHALL之前的状态了。是不是很神奇,这就是AOF持久化方式的好处之一。但是如果AOF文件已经被重写了,那就无法通过这种方法来恢复数据了。
-
虽然优点多多,但AOF方式也同样存在缺陷,比如在同样数据规模的情况下,AOF文件要比RDB文件的体积大。而且,AOF方式的恢复速度也要慢于RDB方式。
-
如果你直接执行BGREWRITEAOF命令,那么redis会生成一个全新的AOF文件,其中便包括了可以恢复现有数据的最少的命令集。
-
如果运气比较差,AOF文件出现了被写坏的情况,也不必过分担忧,redis并不会贸然加载这个有问题的AOF文件,而是报错退出。这时可以通过以下步骤来修复出错的文件:
- 备份被写坏的AOF文件
- 运行redis-check-aof –fix进行修复
- 用diff -u来看下两个文件的差异,确认问题点
- 重启redis,加载修复后的AOF文件