Redis:持久化之AOF

《Redis:持久化之RDB》的最后,我们说到RDB持久化存在一个问题那就是一旦Redis发送异常退出,就会丢失最后一次快照以后更改的所有数据,这可能是几秒或者更长的一个时间丢失。我们也说到如果无法忍受近几秒或者更长的数据丢失,则可以考虑使用AOF方式进行持久化。那么AOF方式又是怎样的呢?往下看。

1. AOF简介

RDB是通过保存数据库中键值对的数据来达到持久化的目的,而AOF则是通过保存Redis服务器所执行的写命令来记录数据库状态。比如以下命令:

在这里插入图片描述

RDB持久化方式则是将aof-test-key1aof-test-key2两个键值对保存在RDB的快照文件中,而对于AOF持久化方式则是将两条set命令保存在AOF文件中。

2. 开启AOF

默认情况下Redis不开启AOF方式的持久化,但我们可以通过appendonly参数启用:

appendonly yes

开启AOF持久化后每执行一条修改数据的命令,Redis就会将该命令写入磁盘的AOF文件。AOF文件的保存位置和RDB文件的位置相同,都是通过dir参数进行设置。默认情况下,AOF持久化生成的文件名为appendonly.aof,我们也可以通过appendfilename参数修改:

appendfilename appendonly.aof

3. 数据恢复

接下来演示一下,Redis基于AOF方式恢复数据的过程。

场景一:验证AOF持久化已经在起作用了。

(1)我们先删除dump.rdbappendonly.aof文件,然后写入k1,然后通过kill命令杀死进程。

在这里插入图片描述

(2)可以看到重新生成了appendonly.aof文件,此时我们重启redis服务,看k1的值是否被持久化。(可以看到k1的值被持久化,而该值就是从AOF文件恢复回来的。)

在这里插入图片描述

场景二:验证redis启动时,是从AOF文件恢复持久化数据,而非dump.rdb。

(1)我们在设置一个k2的值,然后通过redis-cli shutdown停掉redis进程。

在这里插入图片描述

(2)重启redis服务,此时dump.rdb和appendonly.aof都记录了k2的值,无法看出redis重启是否是从aof中恢复的。那么我们再写入k3,然后通过kill -9杀死redis进程。(我们知道用kill方式杀死进程,持久化数据是不会被写进dump.rdb中的)

在这里插入图片描述

(3)重启redis服务,看下k3是否被持久化,若被持久化,则可验证redis启动时,从aof文件中恢复数据。

在这里插入图片描述

4. AOF重写

先看下面一组命令:

在这里插入图片描述

正常来说,Redis的AOF持久化文件会记录这三条命令,然而我们知道k1键值对最终的结果是3,也就是说前两条命令其实是冗余的,因为这两条的执行结果会被第三条命令覆盖。随着执行的命令越来越多,AOF文件的大小也会越来越大,即使内存中实际的数据可能并没有多少。AOF文件越大的另外一个问题就是在Redis进行数据修复的时间也会越长。

很自然地,Redis提供了AOF文件的优化机制,就上面的一组命令而言,Redis在达到一定条件时会自动将前两条无用的记录删除,只保留第三条,这样就能大大减小AOF文件的大小。

4.1 重写的条件

和重写相关的条件配置如下:

auto-aof-rewrite-percentage 100
auto-aof-rewrite-min-size 64mb
  • auto-aof-rewrite-percentage:当目前AOF文件大小超过上一次重写时AOF文件大小的百分之多少时再次进行重写,如果之前没有重写过,则以启动时的AOF文件大小为依据。
  • auto-aof-rewrite-min-size:设置允许重写的最小AOF文件大小,通常情况下当AOF文件很小的时候,即使有很多冗余的命令我们也不需要关心。

当然除了让Redis自动执行重写外,我们也可以通过bgrewirteaof命令手动执行AOF重写。

4.2 重写的原理

我们知道Redis是单线程的,如果重写AOF需要比较长的时间,那么在重写AOF的时候,Redis将长时间无法处理其它的命令,这显然是不合乎情理的。所以Redis在重写的时候,是将重写程序放到子进程进行,这样:

(1)子进程进行 AOF 重写期间,服务器进程(父进程)可以继续处理其他命令。

(2)子进程带有父进程的数据副本,使用子进程而不是线程,可以在避免使用锁的情况下,保证数据的安全性。

使用子进程解决了上面的问题,但是新问题也产生了:因为子进程在进行 AOF 重写期间,服务器进程依然在处理其它命令,这新的命令有可能也对数据库进行了修改操作,使得当前数据库状态和重写后的 AOF 文件状态不一致。

为了解决这个数据状态不一致的问题,Redis 服务器设置了一个 AOF 重写缓冲区,这个缓冲区是在创建子进程后开始使用,当Redis服务器执行一个写命令之后,就会将这个写命令也发送到 AOF 重写缓冲区。当子进程完成 AOF 重写之后,就会给父进程发送一个信号,父进程接收此信号后,就会调用函数将 AOF 重写缓冲区的内容都写到新的 AOF 文件中。

5. 同步磁盘数据

虽然打开AOF持久化方式后,Redis会将写命令记录下来,但实际上,由于操作系统的缓存机制,数据并没有真正地立即写入磁盘,而是进入系统的磁盘缓存。在默认情况下,系统每30秒会执行一次同步操作,以便将磁盘缓存中的内容真正落盘,假设在这30秒的过程中系统异常退出则会导致磁盘缓存中的数据丢失。

一般来讲启动AOF持久化的应用都无法忍受这样的损失,那么就需要Redis在写入AOF文件后主动要求系统将磁盘缓存中的内容同步到磁盘中。在Redis中,我们可以通过appendfsync参数设置同步的时机:

# appendfsync always
appendfsync everysec
# appendfsync no

默认情况下Redis采用everysec规则,即每秒执行一次同步操作。

  • always:表示每次执行写入都会执行同步,这是最安全也是最慢的方式。
  • no:表示不主动进行同步操作,由操作系统每隔30秒做一次同步,这是最快但也是最不安全的方式。

Redis允许同时开启AOF和RDB持久化,此时重新启动Redis后Redis会使用AOF文件来恢复数据,因为相对而言,AOF方式的持久化可能丢失的数据更少。

——End——
更多精彩分享,可扫码关注微信公众号哦。

在这里插入图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值