6.2 AOF持久化机制实战

6.2.1 AOF配置文件说明

在默认情况下,Redis服务器是不会开启AOF持久化机制的,如果需要开启,可以在redis.conf等配置文件里通过修改appendonly参数值为yes来开启.如果要关闭基于AOF的持久化功能,将该参数值设置为no即可.

appendonly yes

appendonly参数开启AOF持久化后,通过appendfsync参数可以设置持久化策略,该参数有3个取值:alwayseverysecno

  • appendfsync参数:设置持久化策略

    • always:每次发生Redis的写命令时都会触发持久化动作,这样可能会影响到Redis甚至是Redis所在服务器的性能

    • everysec:以一秒的频率触发持久化动作,在这种方式下能很好地平衡持久化需求和性能间的关系,一般情况下取这个值

    • no:会由操作系统来决定持久化的频率,这种方式对其他另外两种而言性能最好,但可能每次持久化操作间的间隔有些长,这样当故障发生时可能会丢失较多的数据

  • dir参数:设置持久化文件所在路径

  • appendfilename:设置持久化文件的文件名.默认为appendonly.aof

  • aof-load-truncated:定义AOF文件的加载策略.具体表现为:在AOF持久化文件损坏的前提下,启动Redis时是否会加载,默认取值yes

随着持久化数据的增多,对应的AOF文件会越来越大,这可能会影响到性能.对此,Redis提供了AOF文件重写功能.具体而言,Redis能创建新的AOF文件来替代现有的AOF文件,在数据恢复时,这两个文件的效果是相同的,但新文件不会包含冗余命令,所以文件大小会比原来的小

可以通过如下三个参数来定义重写时的策略:

  • no-appendfsync-on-rewrite:该参数用于平衡性能和安全性.如果该参数取值为yes,那么在重写AOF文件时能提升性能,但可能在重写AOF文件时丢失数据;如果取值为no,则不会丢失数据,但相比于取值为yes时的性能可能会降低.这个参数的默认取值是no

  • auto-aof-rewrite-percentage:该选项指定了AOF文件增长的百分比.当当前AOF文件的大小相对于上一次AOF重写后的大小增长了该参数指定指定的百分比时,Redis将触发一个自动重写操作.前提是AOF文件的大小也超过了auto-aof-rewrite-min-size指定的值.默认该选项的值为100,这意味着当当前AOF文件的大小是上次重写后大小的两倍(即增长了100%)时,Redis 会考虑进行自动重写.但还需要满足AOF文件大小超过auto-aof-rewrite-min-size指定的阈值

  • auto-aof-rewrite-min-size:该选项指定了AOF文件的最小大小.只有当AOF文件的大小超过这个值时,Redis才会考虑进行AOF重写.这是为了防止在AOF文件还很小的时候频繁地进行重写.该选项默认值为64mb,即只有当AOF文件的大小超过64MB时,Redis才会考虑进行自动重写.需要注意的是,仅当AOF文件大小超过这个值时,Redis才会考虑进行重写.但是否真的执行重写还取决于其他条件,例如auto-aof-rewrite-percentage选项

注意:auto-aof-rewrite-percentageauto-aof-rewrite-min-size这两个参数是逻辑且关系,即只有同时满足这2个条件时才会触发重写操作.

此外,可以通过BGREWRITEAOF命令来手动触发针对AOF持久化文件的重写操作

6.2.2 实践AOF持久化

  • step1. 编写配置文件

(base) root@yuanhong chpater6 % cat redis.conf
# 启用AOF持久化机制
appendonly yes

# 持久化频率为每秒持久化1次
appendfsync everysec

# 持久化文件的存储路径
dir /StudyRedisBaseOnDocker/conf/chpater6

# 持久化文件名称
appendfilename "my_appendonly.aof"
  • step2. 根据配置文件启动redis-server

(base) root@yuanhong chpater6 % redis-server redis.conf 

注:此处是直接在宿主机上启动的redis-server,而非在容器中

  • step3. 使用客户端连接后执行一些读写命令

(base) root@yuanhong ~ % redis-cli 
127.0.0.1:6379> GET name
(nil)
127.0.0.1:6379> SET name "Peter"
OK
127.0.0.1:6379> SET age 18
OK
  • step4. 查看AOF持久化文件的内容

(base) root@yuanhong chpater6 % cat my_appendonly.aof
*2
$6
SELECT
$1
0
*3
$3
SET
$4
name
$5
Peter
*3
$3
SET
$3
age
$2
18

逐条命令分析含义:

*2
$6
SELECT
$1
0

这部分内容对应命令SELECT 0.其中:

  • *2:表示接下来的命令有2个参数

  • $6:表示接下来的参数长度为6字节

  • SELECT:表示第一个参数,即命令名SELECT

  • $1:表示接下来的参数长度为1字节

  • 0:表示第二个参数.该参数的含义为要选择的数据库编号,即0

*3
$3
SET
$4
name
$5
Peter

这部分内容对应命令SET name "Peter"

  • *3:表示接下来的命令有3个参数

  • $3:表示接下来的参数长度为3字节

  • SET:表示第1个参数,即命令SET

  • $4:表示接下来的参数长度为4字节

  • name:表示第2个参数,即键名name

  • $5:表示接下来的参数长度为5字节

  • Peter:表示第3个参数,即键name对应的值Peter

*3
$3
SET
$3
age
$2
18

这部分内容对应命令:SET age 18

  • *3:表示接下来的命令有3个参数

  • $3:表示接下来的参数长度为3字节

  • SET:表示第1个参数,即命令SET

  • $3:表示接下来的参数长度为3字节

  • age:表示第2个参数,即键名age

  • $2:表示接下来的参数长度为2字节

  • 18:表示第3个参数,即键age对应的值18

6.2.3 观察重写AOF文件的效果

  • step1. 向键为nameList的list中添加若干数据

127.0.0.1:6379> LPUSH nameList "Peter"
(integer) 1
127.0.0.1:6379> LPUSH nameList "Mary"
(integer) 2
127.0.0.1:6379> LPUSH nameList "Mike"
(integer) 3
127.0.0.1:6379> LPUSH nameList "Tom"
(integer) 4
  • step2. 查看AOF文件

(base) root@yuanhong chpater6 % cat my_appendonly.aof
*2
$6
SELECT
$1
0
*3
$3
SET
$4
name
$5
Peter
*3
$3
SET
$3
age
$2
18
*3
$5
LPUSH
$8
nameList
$5
Peter
*3
$5
LPUSH
$8
nameList
$4
Mary
*3
$5
LPUSH
$8
nameList
$4
Mike
*3
$5
LPUSH
$8
nameList
$3
Tom
  • step3. 运行BGREWRITEAOF命令手动触发AOF文件的重写动作

127.0.0.1:6379> BGREWRITEAOF
Background append only file rewriting started

查看被重写后的AOF文件

 cat my_appendonly.aof
REDIS0009?	redis-ver6.2.13?
redis-bits?@?ctime“?dused-mem??q?
                                 aof-preamble???agenameList##omMikeMaryPeter?namePeter???%?%                                                                    

虽然文件内容被压缩了,但从一些人类可读的字符中仍然可以看到之前AOF文件里记录的多条LPUSH命令被合并为1条

在实际项目里,如果没有特殊情况,一般不会主动运行BGREWRITEAOF命令手动触发AOF文件的重写动作,而是会通过autoaof-rewrite-percentage和auto-aof-rewrite-min-size这两个参数来定义触发重写AOF文件的条件

6.2.4 模拟数据恢复的流程

此处我们基于刚刚的配置文件和AOF文件启动一个容器,看容器中是否存在刚刚写入的键值对

  • step1. 启动容器

(base) root@yuanhong chpater6 % docker run -itd --name redis-server -v /StudyRedisBaseOnDocker/conf/chpater6/redis.conf:/redisConf/redis.conf:rw -v /StudyRedisBaseOnDocker/conf/chpater6/my_appendonly.aof:/StudyRedisBaseOnDocker/conf/chpater6/my_appendonly.aof:rw -p 6379:6379 redis:latest redis-server /redisConf/redis.conf
d46b73c5a69e947baf5f3a461a467438165997357ccc1c365dd20fdbf0754571
  • step2. 确认容器状态

(base) root@yuanhong chpater6 % docker ps
CONTAINER ID   IMAGE          COMMAND                  CREATED         STATUS        PORTS                    NAMES
d46b73c5a69e   redis:latest   "docker-entrypoint.s…"   2 seconds ago   Up 1 second   0.0.0.0:6379->6379/tcp   redis-server
  • step3. 连接redis服务器并验证数据是否存在

(base) root@yuanhong chpater6 % docker exec -it redis-server /bin/bash
root@d46b73c5a69e:/data# redis-cli
127.0.0.1:6379> GET name
"Peter"
127.0.0.1:6379> LRANGE nameList 0 -1
1) "Tom"
2) "Mike"
3) "Mary"
4) "Peter"
127.0.0.1:6379> GET age
"18"

若AOF文件损坏,可以通过redis-check-aof命令进行修复

6.2.5 修复AOF文件

例:

(base) root@yuanhong chpater6 % redis-check-aof --fix /StudyRedisBaseOnDocker/conf/chpater6/my_appendonly.aof
The AOF appears to start with an RDB preamble.
Checking the RDB preamble to start:
[offset 0] Checking RDB file --fix
[offset 27] AUX FIELD redis-ver = '6.2.13'
[offset 41] AUX FIELD redis-bits = '64'
[offset 53] AUX FIELD ctime = '1692079763'
[offset 68] AUX FIELD used-mem = '1077712'
[offset 84] AUX FIELD aof-preamble = '1'
[offset 86] Selecting DB ID 0
[offset 164] Checksum OK
[offset 164] \o/ RDB looks OK! \o/
[info] 3 keys read
[info] 0 expires
[info] 0 already expired
RDB preamble is OK, proceeding with AOF tail...
AOF analyzed: size=164, ok_up_to=164, ok_up_to_line=1, diff=0
AOF is valid

注意:redis-check-aof是一个二进制,不是Redis中的一个命令.且修复后会生成一个RDB文件.

当你使用redis-check-aof --fix命令修复AOF文件时,工具可能会发现AOF中的某些命令序列是不完整或损坏的.为了修复这些问题并确保数据的完整性,工具会进行以下操作:

  1. 它启动一个Redis实例并重播AOF文件中的所有命令,就像Redis在启动时重播AOF文件一样

  2. 之后,它会将这个Redis实例的当前数据集导出为一个RDB文件

  3. 最后,它会将这个新的RDB文件追加到原始的AOF文件中

这个新生成的RDB文件是AOF文件修复过程的一部分.当Redis下次启动并加载这个修复后的AOF文件时,它首先会加载RDB文件中的数据集,然后再继续重播RDB之后的所有AOF命令.这确保了数据的完整性和连续性.

使用这种方法的好处是:

  • RDB是一种紧凑的二进制格式,加载速度非常快

  • 通过将当前数据集导出为RDB格式并追加到AOF文件的方式,可以确保数据的完整性,即使原始AOF文件中的某些部分是损坏的

总之,生成RDB文件是redis-check-aof --fix命令修复AOF文件的一部分,目的是为了确保数据的完整性和提高加载速度

Last updated