一、AOF概述

AOF(Append-Only File)记录Redis中每次的写命令,类似mysql中的binlog,服务重启时会重新执行AOF中的命令将数据恢复到内存中,RDB(按策略持久化)持久化方式记录的粒度不如AOF(记录每条写命令),因此很多生产环境都是开启AOF持久化。AOF中记录了操作和数据,在日志文件中追加完成后才会将内存中的数据进行变更。

AOF(append only file)只追加文件,记录服务器执行的所有写操作命令,并在服务器启动时,通过重新执行这些命令来还原数据集。 AOF 文件中的命令全部以 Redis 协议的格式来保存,新命令会被追加到文件的末尾。

二、AOF持久化流程

#1.客户端的请求写命令会被append追加到AOF缓冲区内;

#2.AOF缓冲区根据AOF持久化策略[always,everysec,no]将操作sync同步到磁盘的AOF文件中;

#3.AOF文件大小超过重写策略或手动重写时,会对AOF文件rewrite重写,压缩AOF文件容量;

#4.Redis服务重启时,会重新load加载AOF文件中的写操作达到数据恢复的目的;

第八章 Redis数据持久化之AOF

三、 AOF配置

开启了AOF之后,RDB就默认不使用了。使用下面的配置开启AOF以及策略。(如果使用AOF,推荐选择always方式持久化,否则在高并发场景下,每秒钟会有几万甚至百万条请求,如果使用everysec的方式的话,万一服务器挂了那几万条数据就丢失了)。

#开启AOF持久化
appendonly yes

#AOF文件名
appendfilename "appendonly.aof"

#AOF文件存储路径 与RDB是同一个参数
dir "/opt/app/redis6/data"

#AOF策略,一般都是选择第一种[always:每个命令都记录],[everysec:每秒记录一次],[no:看机器的心情高兴了就记录]
appendfsync always
# appendfsync everysec
# appendfsync no

#aof文件大小比起上次重写时的大小,增长100%(配置可以大于100%)时,触发重写。[假如上次重写后大小为10MB,当AOF文件达到20MB时也会再次触发重写,以此类推]
auto-aof-rewrite-percentage 100 

#aof文件大小超过64MB时,触发重写
auto-aof-rewrite-min-size 64mb 

#是否在后台写时同步单写,默认值no(表示需要同步).这里的后台写,表示后台正在重写文件(包括bgsave和bgrewriteaof.bgrewriteaof网上很多资料都没有涉及到。其实关掉bgsave之后,主要的即是aof重写文件了).no表示新的主进程的set操作会被阻塞掉,而yes表示新的主进程的set不会被阻塞,待整个后台写完成之后再将这部分set操作同步到aof文件中。但这可能会存在数据丢失的风险(机率很小),如果对性能有要求,可以设置为yes,仅在后台写时会异步处理命令.
no-appendfsync-on-rewrite no

# 指redis在恢复时,会忽略最后一条可能存在问题的指令。默认值yes。即在aof写入时,可能存在指令写错的问题(突然断电,写了一半),这种情况下,yes会log并继续,而no会直接恢复失败.
aof-load-truncated yes

四、AOF持久化策略

AOF分别有三种备份策略,分别是[always:每个命令都记录],[everysec:每秒记录一次],[no:看机器的心情高兴了就记录],针对这三种策略给出如下说明。

1.策略说明

策略 说明 优点
always 每次执行,都会持久化到AOF文件中 不丢失数据
everysec 每秒持久化一次 减少IO
no 根据服务器性能持久化 全自动

2.策略抉择

命令 Always Everysec no
优点 不丢失数据 每秒一次fsync,减少IO 不用管,全自动
缺点 IO开销大 丢1秒钟的数据 不可控

五、AOF模式的优点

第八章 Redis数据持久化之AOF

1.使用AOF Redis会更具有可持久性(durable):你可以有很多不同的fsync策略:没有fsync,每秒fsync,每次请求时fsync。使用默认的每秒fsync策略,写性能也仍然很不错(fsync是由后台线程完成的,主线程继续努力地执行写请求),即便你也就仅仅只损失一秒钟的写数据。

2.AOF日志是一个追加文件,所以不需要定位,在断电时也没有损坏问题。即使由于某种原因文件末尾是一个写到一半的命令(磁盘满或者其他原因),redis-check-aof工具也可以很轻易的修复。

3.当AOF文件变得很大时,Redis会自动在后台进行重写。重写是绝对安全的,因为Redis继续往旧的文件中追加,使用创建当前数据集所需的最小操作集合来创建一个全新的文件,一旦第二个文件创建完毕,Redis就会切换这两个文件,并开始往新文件追加。

4.AOF文件里面包含一个接一个的操作,以易于理解和解析的格式存储。你也可以轻易的导出一个AOF文件。例如,即使你不小心错误地使用FLUSHALL命令清空一切,如果此时并没有执行重写,你仍然可以保存你的数据集,你只要停止服务器,删除最后一条命令,然后重启Redis就可以。

总结:
1)备份机制更稳健,丢失数据概率更低。
2)可读的日志文本,通过操作AOF稳健,可以处理误操作。

六、AOF重写机制

1.AOF重写机制概述

1.因为 AOF 的运作方式是不断地将命令追加到文件的末尾,所以随着写入命令的不断增加, AOF 文件的体积也变得越来越大。举个例子,如果你对一个计数器调用了 100 次 INCR ,那么仅仅是为了保存这个计数器的当前值, AOF 文件就需要使用 100 条记录。然而在实际上,只使用一条 SET 命令已经足以保存计数器的当前值了,其余 99 条记录实际上都是多余的。

2.为了处理这种情况, Redis 支持一种有趣的特性:可以在不断服务客户端的情况下,对 AOF 文件进行重建。执行 BGREWRITEAOF 命令, Redis 将生产一个新的 AOF 文件,这个文件包含重建当前数据集所需的最少命令。

2. AOF重写配置

配置名 含义
appendonly 开启AOF持久化功能
auto-aof-rewrite-min-size 触发重写的最小尺寸
auto-aof-rewrite-percentage AOF文件增长率
aof_current_size AOF当前尺寸
aof_base_size AOF上次启动和重写的尺寸(单位:字节)

3. AOF重写触发机制

根据配置,AOF持久化触发机制如下:

1.aof_current_size > auto-aof-rewrite-min-size
2.(aof_current_size - aof_base_size) / aof_base_size > auto-aof-rewrite-percentage

4. AOF重写流程

1.bgrewriteaof触发重写,判断是否当前有bgsave或bgrewriteaof在运行,如果有,则等待该命令结束后再继续执行。

2.主进程fork出子进程执行重写操作,保证主进程不会阻塞。

3.子进程遍历redis内存中数据到临时文件,客户端的写请求同时写入aof_buf缓冲区和aof_rewrite_buf重写缓冲区保证原AOF文件完整以及新AOF文件生成期间的新的数据修改动作不会丢失。

4.子进程写完新的AOF文件后,向主进程发信号,父进程更新统计信息。2).主进程把aof_rewrite_buf中的数据写入到新的AOF文件。

5.使用新的AOF文件覆盖旧的AOF文件,完成AOF重写。

第八章 Redis数据持久化之AOF

第八章 Redis数据持久化之AOF

七、AOF持久化缺点

1.对同样的数据集,AOF文件通常要大于等价的RDB文件。

2.AOF可能比RDB慢,这取决于准确的fsync策略。通常fsync设置为每秒一次的话性能仍然很高,如果关闭fsync,即使在很高的负载下也和RDB一样的快。不过,即使在很大的写负载情况下,RDB还是能提供能好的最大延迟保证。

3.在过去,我们经历了一些针对特殊命令(例如,像BRPOPLPUSH这样的阻塞命令)的罕见bug,导致在数据加载时无法恢复到保存时的样子。这些bug很罕见,我们也在测试套件中进行了测试,自动随机创造复杂的数据集,然后加载它们以检查一切是否正常,但是,这类bug几乎不可能出现在RDB持久化中。为了说得更清楚一点:Redis AOF是通过递增地更新一个已经存在的状态,像MySQL或者MongoDB一样,而RDB快照是一次又一次地从头开始创造一切,概念上更健壮。
但是,
1)要注意Redis每次重写AOF时都是以当前数据集中的真实数据从头开始,相对于一直追加的AOF文件(或者一次重写读取老的AOF文件而不是读内存中的数据)对bug的免疫力更强。
2)我们还没有收到一份用户在真实世界中检测到崩溃的报告。

总结:
1)比起RDB占用更多的磁盘空间。
2)恢复备份速度要慢。
3)每次读写都同步的话,有一定的性能压力。
4)存在个别Bug,造成恢复不能。 

八、AOF持久化优缺点总结

优点:可以最大程度保证数据不丢失
缺点:日志记录量级比较大

第八章 Redis数据持久化之AOF

九、RDB与AOF抉择

1.RDB与AOF比较

命令 RDB AOF
启动优先级
体积
恢复速度
数据安全性 丢数据 根据策略的不同,丢数据的情况也不同
轻重

2.官网建议

1.RDB持久化方式能够在指定的时间间隔能对你的数据进行快照存储
2.AOF持久化方式记录每次对服务器写的操作,当服务器重启的时候会重新执行这些命令来恢复原始的数据,AOF命令以redis协议追加保存每次写的操作到文件末尾. 
3.Redis还能对AOF文件进行后台重写,使得AOF文件的体积不至于过大
4.只做缓存:如果你只希望你的数据在服务器运行的时候存在,你也可以不使用任何持久化方式.
5.同时开启两种持久化方式
6.在这种情况下,当redis重启的时候会优先载入AOF文件来恢复原始的数据, 因为在通常情况下AOF文件保存的数据集要比RDB文件保存的数据集要完整.
7.RDB的数据不实时,同时使用两者时服务器重启也只会找AOF文件。那要不要只使用AOF呢? 
建议不要,因为RDB更适合用于备份数据库(AOF在不断变化不好备份), 快速重启,而且不会有AOF可能潜在的bug,留着作为一个万一的手段。
8.性能建议
因为RDB文件只用作后备用途,建议只在Slave上持久化RDB文件,而且只要15分钟备份一次就够了,只保留save 900 1这条规则。
如果使用AOF,好处是在最恶劣情况下也只会丢失不超过两秒数据,启动脚本较简单只load自己的AOF文件就可以了。
代价,一是带来了持续的IO,二是AOF rewrite的最后将rewrite过程中产生的新数据写到新文件造成的阻塞几乎是不可避免的。
只要硬盘许可,应该尽量减少AOF rewrite的频率,AOF重写的基础大小默认值64M太小了,可以设到5G以上。
默认超过原大小100%大小时重写可以改到适当的数值。

第八章 Redis数据持久化之AOF

3. RDB与AOF之间的优劣势

#1.RDB的优点
1.压缩后的二进制文件,适用于备份、全量复制及灾难恢复。
2.RDB恢复数据性能优于AOF方式。

#2.RDB的缺点
1.无法做到实时持久化,每次都要创建子进程,频繁操作成本过高
2.保存后的二进制文件,不同版本直接存在兼容性问题

#3.AOF的优点
1.以文本形式保存,易读
2.记录写操作保证数据不丢失

#4.AOF的缺点
1.存储所有写操作命令,且文件为文本格式保存,未经压缩,文件体积高。
2.恢复数据时重放AOF中所有代码,恢复性能弱于RDB方式。

十、 AOF与RDB混合

看了上面的RDB和AOF的介绍后,我们可以发现,使用RDB持久化会有数据丢失的风险,但是恢复速度快,而使用AOF持久化可以保证数据完整性,但恢复数据的时候会很慢。于是从Redis4之后新增了混合AOF和RDB的模式,先使用RDB进行快照存储,然后使用AOF持久化记录所有的写操作,当重写策略满足或手动触发重写的时候,将最新的数据存储为新的RDB记录。这样的话,重启服务的时候会从RDB何AOF两部分恢复数据,即保证了数据完整性,又提高了恢复的性能。
	
开启混合模式后,每当bgrewriteaof命令之后会在AOF文件中以RDB格式写入当前最新的数据,之后的新的写操作继续以AOF的追加形式追加写命令。当redis重启的时候,加载 aof 文件进行恢复数据:先加载 rdb 的部分再加载剩余的 aof部分。

1.混合配置

修改下面的参数即可开启AOF,RDB混合持久化
aof-use-rdb-preamble yes

2.混合模式示例

开启混合持久化模式后,重写之后的aof文件里和rdb一样存储二进制的快照数据,继续往redis中进行写操作,后续操作在aof中仍然是以命令的方式追加。因此重写后aof文件由两部分组成,一部分是类似rdb的二进制快照,另一部分是追加的命令文本。

# step1: 进入Redis, 写入数据
[root@alvin-test-os redis]# redis-cli --raw
127.0.0.1:6379> set name alvin
OK
127.0.0.1:6379> set age 18
OK
127.0.0.1:6379> set add 上海
OK
127.0.0.1:6379> exit

# Step 2: 查看备份文件
[root@alvin-test-os redis]# ll data/
总用量 8
-rw-r--r--. 1 root root 121 11月 24 15:39 appendonly.aof
-rw-r--r--. 1 root root 116 11月 24 15:39 dump.rdb

[root@alvin-test-os redis]# cat data/appendonly.aof | grep add
add
[root@alvin-test-os redis]# cat data/appendonly.aof
*2
$6
SELECT
$1
0
*3
$3
set
$4
name
$5
alvin
*3
$3
set
$3
age
$2
18
*3
$3
set
$3
add
$6
上海

# Step 3: 启动备份
[root@alvin-test-os redis]# redis-cli --raw
127.0.0.1:6379> BGREWRITEAOF
Background append only file rewriting started
127.0.0.1:6379> exit

# Step 4: 查看配置文件发现AOF备份文件变成了二进制文件
[root@alvin-test-os redis]# cat data/appendonly.aof
REDIS0009�  redis-ver6.0.9�
�edis-bits�@�ctime��_used-mem��4
 aof-preamble���namealvinadd上海age���6����&
[root@alvin-test-os redis]#

# Step 5: 再次写入文件
[root@alvin-test-os redis]# redis-cli --raw
127.0.0.1:6379> set company 上海
OK
127.0.0.1:6379> exit

# Step 6:再次查看备份文件发现被分成了两份,一份二进制,一份AOF备份
[root@alvin-test-os redis]# cat data/appendonly.aof
REDIS0009�  redis-ver6.0.9�
�edis-bits�@�ctime��_used-mem��4
 aof-preamble���namealvinadd上海age���6����&*2
$6
SELECT
$1
0
*3
$3
set
$7
company
$15
上海

3.备份Redis数据

1.Redis 对于数据备份是非常友好的,因为你可以在服务器运行的时候对 RDB 文件进行复制: RDB 文件一旦被创建,就不会进行任何修改。
2.当服务器要创建一个新的 RDB 文件时,它先将文件的内容保存在一个临时文件里面,当临时文件写入完毕时,程序才使用临时文件替换原来的 RDB 文件。
3.这也就是说,无论何时, 复制 RDB 文件都是绝对安全的。

#以下是我们的建议:
1.创建一个定期任务(cron job), 每小时将一个 RDB 文件备份到一个文件夹, 并且每天将一个 RDB 文件备份到另一个文件夹。
2.确保快照的备份都带有相应的日期和时间信息, 每次执行定期任务脚本时, 使用 find 命令来删除过期的快照: 比如说, 你可以保留最近 48 小时内的每小时快照, 还可以保留最近一两个月的每日快照。
3.至少每天一次, 将 RDB 备份到你的数据中心之外, 或者至少是备份到你运行 Redis 服务器的物理机器之外。

4.RDB持久化高级配置

#编辑配置文件
[root@db01 redis]# vim /etc/redis/6379/redis.conf
#后台备份进程出错时,主进程停不停止写入? 主进程不停止容易造成数据不一致
stop-writes-on-bgsave-error yes
#导出的rdb文件是否压缩 如果rdb的大小很大的话建议这么做
rdbcompression yes
#导入rbd恢复时数据时,要不要检验rdb的完整性 验证版本是不是一致
rdbchecksum yes

5.AOF持久化高级配置

#编辑配置文件
[root@db01 redis]# vim /etc/redis/6379/redis.conf
#正在导出rdb快照的过程中,要不要停止同步aof
no-appendfsync-on-rewrite yes
#aof文件大小比起上次重写时的大小,增长率100%时重写,缺点:业务开始的时候,会重复重写多次
auto-aof-rewrite-percentage 100
#aof文件,至少超过64M时,重写
auto-aof-rewrite-min-size 64mb

相关文章:

  • 2022-01-05
猜你喜欢
  • 2021-04-11
  • 2021-11-09
  • 2021-10-27
  • 2021-06-03
  • 2021-08-09
  • 2021-12-03
相关资源
相似解决方案