12. Redis 之 AOF持久化方式

阿里云国内75折 回扣 微信号:monov8
阿里云国际,腾讯云国际,低至75折。AWS 93折 免费开户实名账号 代冲值 优惠多多 微信号:monov8 飞机:@monov6


Redis 之 AOF持久化方式


AOF简介

Redis的持久化方式之一RDB是通过保存数据库的键值对数据来记录数据库的状态。而另一种持久化策略AOF就是通过保存Redis服务器所执行的命令来记录数据库状态的。

比如执行如下命令:

127.0.0.1:6379> set str1 "123"
OK
127.0.0.1:6379> sadd str2 "a" "b" "c"
(integer) 3
127.0.0.1:6379>

RDB持久化方式就是将 ​​str1​​​ 和 ​​str2​​​ 这两个键值对保存在RDB文件中,而AOF持久化则是将执行的 ​​set​​​和 ​​sadd​​两个命令保存在AOF文件中。

AOF配置信息

下面我们看一下【redis.conf】配置文件中关于AOF的配置信息。

开启AOF

appendonly no

说明:是否开启AOF持久化方式。​​no​​​ 不开启。​​yes​​开启。默认是不开启的,即:redis默认采用RDB方式持久化。

解释:

​ redis的​​AOF​​持久化方式默认是不开启的,它的出现是为了弥补RDB的不足(数据不一致),所以它采用日志的形式来记录每个写操作,并追加到文件中。redis重启会根据日志文件的内容将写指令从前到后执行一次以完成数据的恢复工作。

​ 默认redis使用的是​​RDB​​​方式持久化,这种方式在需要应用中就已经足够用了。但是redis如果中途宕机,会导致可能几分钟的数据丢失(根据save策略进行持久化)。​​Append Only File​​是另一种持久化方式,可以提供更好的持久化特征。redis会把每次写入的数据在接收后都写入【appendonly.aof】文件,如果AOF方式开启了。每次启动时redis都会先把这个文件的数据读入内存里,先忽略RDB文件。

注意:RDB和AOF可以同时开启,不会出现问题。redis会优先加载AOF,此时AOF是一种更好的持久化保证。

AOF文件名

appendfilename "appendonly.aof"

说明:指定AOF日志文件的文件名,默认使用"appendonly.aof"

文件位置

AOF保存文件的位置和RDB保存文件的位置一样,都是通过【redis.conf】配置文件的【dir】来配置。

12. Redis 之 AOF持久化方式_redis

可以通过命令【config get dir】来获取保存路径,如下:

12. Redis 之 AOF持久化方式_数据_02

AOF持久化策略

同步方法的调用,告诉操作系统去真正的写数据到硬盘中,而不是等待更多的数据在输出缓存区。一些系统会真正的刷新数据到硬盘,而另一些则是尝试尽可能快的去执行。

# appendfsync always
appendfsync everysec
# appendfsync no

说明:指定AOF持久化模式。

  • no: 不同步,仅仅让操作系统在需要的时候刷新数据,速度最快。
  • always:在每次写入后都同步;慢,但是最安全。
  • everysec:每一秒同步一次,在速度和安全方面都适中。可能丢失一秒的数据。

解释:

​ 默认的同步模式就是"everysec",这种在速度和数据安全方面中达到一个适中。这取决于你的理解,如果你可以允许放置​​no​​​来让操作系统在需要的时候去刷新到输出缓存中,也许更好的方式就是RDB。(如果你可以忍受丢失一些数据,可以使用默认的持久化方式–快照)。相反的话,可以使用一个很慢的但是比​​everysec​​​更加的方式–​​always​​。

注意:如果不确定使用哪种方式,那就使用​​everysec​

重写时是否同步

no-appendfsync-on-rewrite no

解释:fsync(同步) 。​​no-appendfsyc-on-rewrite​​​ 字段默认设置为​​no​​。

​ 在AOF重写或是写入RDB文件的时候,会执行大量的IO,此时对于​​everysec​​​和​​always​​的aof模式来说,执行fsync会造成阻塞过长时间。

​ 如果对延迟要求很高的应用,这个字段可以设置为​​yes​​​,否则设置为​​no​​​,这样对持久化特性来说这是更加安全的选择。设置为​​yes​​​表示​​rewrite​​​期间对新写的操作不fsync,暂时存在内存中,等​​rewrite​​​完成后再写入。默认为​​no​​​,建议为​​yes​​。Linux的默认fsync策略是30秒,可能丢失30秒数据。

重写配置

auto-aof-rewrite-percentage 100
auto-aof-rewrite-min-size 64mb

解释:

  • ​auto-aof-rewrite-percentage​

aof自动重写配置,当目前aof文件大小超过上一次重写的aof文件大小的百分之多少进行重写,即当AOF文件增加到一定的大小的时候,redis能够调用​​bgrewriteaof​​对日志文件进行重写。当前AOF文件大小是上次日志重写的AOF文件大小的2倍(设置为100)时,自动启动新的日志重写进程。

  • ​auto-aof-rewrite-min-size​

设置允许重写的最小aof文件大小,避免了达到约定百分比但尺寸依然很小的情况还要重写.

截断导入

aof-load-truncated yes

解释:

​ AOF文件可能在尾部不完整的,当redis启动的时候,aof文件的数据被载入内存。重启可能发生在redis
所在的主机操作系统宕机后,尤其在ext4文件系统没有加上data=ordered选项(redis宕机或者异常终止
不会造成尾部不完整现象)。出现这种情况,可以选择让redis退出,或者导入尽可能多的数据。如果
选择yes,当截断的aof文件被导入的时候,会发布一个log给客户端然后load。如果是no,用户必须手动
​​​redis-check-aof​​修复AOF文件才可以。

混合持久化


重启redis恢复数据集时,很少会使用RDB来恢复内存状态,因为会丢失大量数据。通常会使用AOF日志恢复数据,但是重放AOF日志性能相对于RDB来说要慢得多,这样在Redis实例很大的情况下,启动需要花费很长时间。Redis4.0为了解决这个问题,带来了新的持久化选项—混合持久化。

aof-use-rdb-preamble yes

说明:

​ 如果开启了混合持久化,aof在重写时,不再是单纯将内存数据转换为RESP命令写入aof文件,而是将重写这一刻之前的内存做RDB快照处理,并且将RDB快照内容和增量的aof修改内存数据的命令存在一起,都写入新的AOF文件,新的AOF文件一开始不叫​​appendonly.aof​​,等到重写完成之后,新的aof文件才会进行改名,原子的覆盖原有的aof文件,完成新旧两个aof文件的替换。于是在redis重启的时候,可以先加载rdb文件,然后再重放增量的aof日志就可以完全替代之前的aof全量文件重放,因此重启效率大幅得到提高。

数据修复

将appendonly设置为yes,重启redis之后就会进行AOF文件的载入。若AOF文件有损坏,例如由于某些原因,里面有些命令变成乱码。此时redis还可以重新启动吗?

​ 在AOF文件随便加一些字符,保存后重连redis。可发行此时redis无法在重新启动。那么此时如何恢复数据呢?在redis的文件目录下有一个叫​​redis-check-aof​​的工具。使用如下命令可修复AOF文件:

redis-check-aof.exe --fix appendonly.aof

上述命令会清除所有不符合语法的命令。

12. Redis 之 AOF持久化方式_持久化_03


从上图可以看出,AOF文件是不正常的文件。

当启动redis的时候,会提醒用户进行修复:

12. Redis 之 AOF持久化方式_redis_04

使用 ​​redis-check-aof --fix filename​​ 命令修复

12. Redis 之 AOF持久化方式_redis_05

这样就可以正常启动了

12. Redis 之 AOF持久化方式_持久化_06

AOF重写

由于AOF持久化是Redis不断将写命令记录到 AOF 文件中,随着Redis不断的进行,AOF 的文件会越来越大,文件越大,占用服务器内存越大以及 AOF 恢复要求时间越长。为了解决这个问题,Redis新增了重写机制,当AOF文件的大小超过所设定的阈值时,Redis就会启动AOF文件的内容压缩,只保留可以恢复数据的最小指令集。可以使用命令 bgrewriteaof 来重写。

比如对于如下命令:

12. Redis 之 AOF持久化方式_redis_07

如果不进行 AOF 文件重写,那么 AOF 文件将保存四条 SADD 命令,如果使用AOF 重写,那么AOF 文件中将只会保留下面一条命令:

sadd animals "cat" "dog" "tiger" "panda" "lion" "pig"

也就是说 AOF 文件重写并不是对原文件进行重新整理,而是直接读取服务器现有的键值对,然后用一条命令去代替之前记录这个键值对的多条命令,生成一个新的文件后去替换原来的 AOF 文件。

AOF 文件重写触发机制:
通过 redis.conf 配置文件中的 auto-aof-rewrite-percentage:默认值为100,以及auto-aof-rewrite-min-size:64mb 配置,也就是说默认Redis会记录上次重写时的AOF大小,默认配置是当AOF文件大小是上次rewrite后大小的一倍且文件大于64M时触发。

这里再提一下,我们知道 Redis 是单线程工作,如果重写 AOF 需要比较长的时间,那么在重写 AOF 期间,Redis将长时间无法处理其他的命令,这显然是不能忍受的。Redis为了克服这个问题,解决办法是将 AOF 重写程序放到子程序中进行,这样有两个好处:

  1. 子进程进行 AOF 重写期间,服务器进程(父进程)可以继续处理其他命令。
  2. 子进程带有父进程的数据副本,使用子进程而不是线程,可以在避免使用锁的情况下,保证数据的安全性。

使用子进程解决了上面的问题,但是新问题也产生了:因为子进程在进行 AOF 重写期间,服务器进程依然在处理其它命令,这新的命令有可能也对数据库进行了修改操作,使得当前数据库状态和重写后的 AOF 文件状态不一致。
  为了解决这个数据状态不一致的问题,Redis 服务器设置了一个 AOF 重写缓冲区,这个缓冲区是在创建子进程后开始使用,当Redis服务器执行一个写命令之后,就会将这个写命令也发送到 AOF 重写缓冲区。当子进程完成 AOF 重写之后,就会给父进程发送一个信号,父进程接收此信号后,就会调用函数将 AOF 重写缓冲区的内容都写到新的 AOF 文件中。这样将 AOF 重写对服务器造成的影响降到了最低。

AOF的优缺点

  • 优点
  1. AOF 持久化的方法提供了多种的同步频率,即使使用默认的同步频率每秒同步一次,Redis 最多也就丢失 1 秒的数据而已。
  2. AOF 文件使用 Redis 命令追加的形式来构造,因此,即使 Redis 只能向 AOF 文件写入命令的片断,使用 redis-check-aof 工具也很容易修正 AOF 文件。
  3. AOF 文件的格式可读性较强,这也为使用者提供了更灵活的处理方式。例如,如果我们不小心错用了 FLUSHALL 命令,在重写还没进行时,我们可以手工将最后的 FLUSHALL 命令去掉,然后再使用 AOF 来恢复数据。
  • 缺点
  1. 对于具有相同数据的的 Redis,AOF 文件通常会比 RDB 文件体积更大。
  2. 虽然 AOF 提供了多种同步的频率,默认情况下,每秒同步一次的频率也具有较高的性能。但在 Redis 的负载较高时,RDB 比 AOF 具好更好的性能保证。
  3. RDB 使用快照的形式来持久化整个 Redis 数据,而 AOF 只是将每次执行的命令追加到 AOF 文件中,因此从理论上说,RDB 比 AOF 方式更健壮。官方文档也指出,AOF 的确也存在一些 BUG,这些 BUG 在 RDB 没有存在。

最佳实践

参考:http://www.javaboy.org/2019/0615/redis-aof.html

  1. 如果redis只做缓存服务器,那么可以不使用任何持久化方式。
  2. 同时开启两种持久化方式,在这种情况下,当redis重启的时候会优先载入AOF文件来恢复原始的数据,因为在通常情况下,AOF文件保存的数据集要比RDB文件保存的数据集要完整。RDB的数据不完整时,同时使用两者时服务器重启也只会找AOF。那要不要只使用AOF呢?建议不要,因为RDB更适合用于备份数据库(AOF在不断变化不好备份),快速重启,而且不会有AOF可能潜在bug,留着做万一的手段。
  3. 因为RDB文件只用作后备用途,建议只在Slave上持久化RDB文件,而且只要15分钟备份一次就够了,只保留save 900 1 这一条规则。
  4. 如果Enable AOF,好处是在最恶劣情况下也只会丢失不超过两秒数据,启动脚本较简单只load自己的AOF文件就可以了。代价一是带来了持续的IO,二是AOF rewrite的最后将rewrite过程中产生的新数据写到新文件造成的阻塞几乎是不可避免的。只要硬盘许可,应该尽量减少AOF rewrite的频率,AOF重写的基础大小默认值64M太小了,可以设置到5G以上。默认超过原大小100%大小时重写可以改到适当的数据。
  5. 如果不Enable AOF,仅靠Master-Slave Replication 实现高可用性也可以。能省掉一大笔IO,也减少了rewrite 时带来的系统波动。代价是如果Master/Slave 同时宕掉,会丢失十几分钟的数据,启动脚本必要比较两个Master/Slave 中的RDB文件,载入较新的那个。

那么对于 AOF 和 RDB 两种持久化方式,我们应该如何选择呢?
  如果可以忍受一小段时间内数据的丢失,毫无疑问使用 RDB 是最好的,定时生成 RDB 快照(snapshot)非常便于进行数据库备份, 并且 RDB 恢复数据集的速度也要比 AOF 恢复的速度要快,而且使用 RDB 还可以避免 AOF 一些隐藏的 bug;否则就使用 AOF 重写。


阿里云国内75折 回扣 微信号:monov8
阿里云国际,腾讯云国际,低至75折。AWS 93折 免费开户实名账号 代冲值 优惠多多 微信号:monov8 飞机:@monov6
标签: redis

“12. Redis 之 AOF持久化方式” 的相关文章