文章目录
AOF简介
RDB的弊端
对于前篇介绍的RDB持久化,他也并不是完美的,它存在有他的弊端,主要如下:
- 数据量大时,存储效率低。
- 大数据量时IO性能低。
- bgsave会通过fork创建子进程,产生额外的内存消耗。
- 宕机时,会存在数据丢失。
有什么解决方案呢,针对上面几个问题,有如下几个解决思路:
- 每次保存时,不记录全部数据,只存部分数据。
- 把记录数据改为记录操作过程。
- 对所有操作都记录,避免数据丢失。
AOF概念
- AOF(append only file)持久化:以独立日志的方式记录每次写命令,重启时执行AOF文件中的命令,达到数据恢复的目的。与RDB相比可以简单描述为改记录数据为记录数据产生的过程。
- AOF主要解决了数据持久化的实时性,是目前redis持久化的主流方式。
AOF持久化策略
- always:每次操作都同步到AOF文件中,数据没有误差,不过性能较低,不建议使用。
- everysec:每秒保存一次操作到IAOF文件中,数据准确性较高,性能较高,推荐使用,也是默认配置。
- no:持久化由系统控制,整体过程不可控。
开启AOF具体配置
- 是否开始AOF:
appendonly yes|no
。 - AOF持久化策略:
appendfsync always|everysec|no
。 - AOF文件名:
appendfilename filename
,默认为appendonly.aof,建议配置为appendlong-[端口号].aof。 - AOF文件存放路径:
dir
。
下面我们实际操作一下,首先修改配置文件:
这边我们配置的是记录每一个操作,一个是因为以我们手动操作的速度,这个配置和每秒存一次的结果是一样的,另一个是交由系统去做的话,不受控,不方便进行数据展示。下面我们启动redis服务,去data目录下看看这个appendonly-6379.aof文件:
此时数据量大小为0,因为我们还没有对redis进行操作,我们先随便往里面塞2条数据,然后再看看appendonly-6379.aof的大小:
这时可以看到aof文件有85字节了,下面我们看看这个文件到底存的一些什么:
如果只看我框出来的内容的话,还是很容易看懂这是记录的我之前所执行的操作,而AOF也正是凭借着记录下来的操作记录,从而做到数据还原。
AOF的重写概念
我们先考虑这样一个问题,如果我进行如下操作:
set name jam
set name tom
set name jack
set age 28
set age 22
set age 18
那么aof文件中会是什么内容呢,结合上面我们看到的aof文件的内容,难道会把我们这6条操作都记录下吗?这个是有可能的,具体原因看完这一节就会知道。
下面说回正题,上面的6个操作,实际上是对2个key进行的,就最终的结果来说,应该只需要set name jack
和set age 18
就可以了,其余的是多余的操作。在实际的场景中,我们的操作肯定不止这6条,其中也肯定会有对同一个key进行操作的情况,这样记录很多多余的操作会使aof文件过大,这时,就有一个解决方案:重写aof文件。
AOF重写的作用
- 降低磁盘占用率,提高磁盘利用率。
- 提高持久化效率,降低持久化写时间,提高IO性能。(去掉多余的命令自然要写入的内容减少,效率提高)
- 降低数据恢复时间,提高数据恢复效率。(去掉多余的命令,数据恢复时需要执行的命令减少,提高效率)
AOF重写规则
- 进程内已超时的数据不会再记录。
- 忽略无效的指令,如get操作,重写时直接根据进程内的数据生成写入操作。
- 对多条命令合并,如
lpush list a
,lpush list b
,lpush list c
会合并为lpush list a b c
。
AOF重写操作
说了这么多,AOF的重写到底怎么操作呢,有2个方式:
- 手动执行指令:
bgrewriteaof
- 自动重写:通过配置文件配置(详细的后面说)
auto-aof-rewrite-min-size size
:aof文件大小达到指定的size就触发重写。
auto-aof-rewrite-percentage percentage
:aof文件大小达到某一百分比就触发重写。
手动执行
我们先看一下手动执行的方式,先对一个key进行重复操作,然后看一下aof文件的内容:
可以看到之前的3个操作都记录下来了,然后我们执行下重写操作。
然后再来看一下aof文件的内容:
可以看到文件内容已经发生变化了,这就是重写后的aof文件。
自动AOF重写
先回顾一下上面说的两个参数:
auto-aof-rewrite-min-size size
:aof文件大小达到指定的size就触发重写,默认的size比较大,32M、64M等。auto-aof-rewrite-percentage percentage
:aof文件大小达到某一百分比就触发重写。
然后介绍两个新参数,这两个参数不是在配置文件中的,而是redis的参数:
aof_current_size
:aof当前缓冲区大小。aof_base_size
:基础尺寸。
对于 auto-aof-rewrite-min-size size
这个参数,指的是如果当前aof缓冲区大小(aof_current_size
)超过了这个自定义的size,就触发重写。
对于auto-aof-rewrite-percentage percentage
这个参数,有一个计算百分比的公式,当这个满足这个公式时,就触发重写:
(aof_current_size
- aof_base_size
) / aof_base_size
>= auto-aof-rewrite-percentage
自动重写AOF在这就不再做演示,下面我们看一下aof_current_size
、aof_base_size
这两个参数怎么看,在redis客户端输入命令:info persistence
:
AOF工作原理
AOF重写的原理大体上和bgsave
类似,都是通过fork一个子进程,让子进程在后台执行。
always
everysec
可以看到,everysec比always多了一个缓冲区,用来存储这1秒内的操作。
everysec + 重写AOF
可以看到,当everysec结合重写AOF后,逻辑复杂了一些,everysec的主要逻辑没变,只是在生成缓冲区的同时生成了一个aof重写缓冲区,这里面存的就是重写后的aof数据,当执行重写aof操作时,aof重写fork的那个子进程就会从aof重写缓冲区拿数据,然后写入一个aof临时文件,最后,这个aof临时文件和aof文件合并,变成重写后的aof文件。
RDB对比AOF
持久化方式 | RDB | AOF |
---|---|---|
占用存储空间 | 小(数据级:可以压缩数据) | 大(指令级) |
存储速度 | 慢(数据量大时) | 快 |
恢复速度 | 快 | 慢(需要执行指令) |
数据安全性 | 会丢失数据 | 根据策略决定 |
资源消耗 | 高/重量级 | 低/轻量级 |
启动优先级 | 低 | 高 |
选择RDB还是AOF?
- 对数据非常敏感,建议使用默认的AOF持久化方案。
- AOF默认策略时everysec,也可能存在丢失一秒内数据的情况。
- 注意:由于AOF文件存储体积较大,恢复速度较慢。
- 数据成阶段性有效,建议使用RDB。
- 数据可以良好的做到阶段内无丢失,且恢复速度较快。
- 注意:用RDB实现紧凑的持久化会降低redis的效率。
- 综合对比:
- RDB与AOF的选择就是做一种权衡,各有利弊。
- 如果不能承受数分钟以内的数据丢失,对业务数据非常敏感,建议使用AOF。
- 如果能承受数分钟以内的数据丢失,且追求大数据集的恢复速度,建议使用RDB。
- 灾难恢复选用RDB。(速度快)
- 双重保险,RDB、AOF同时打开,重启后,优先使用AOF恢复数据,降低丢失的数据量。