Redis持久化之RDB+AOF+混合持久化实战演练

文章目录

  • 前言
  • 一、RDB持久化
    • 1、介绍以及测试
    • 2、手动持久化方式bgsave
    • 3、save与bgsave比较
    • 3、优缺点
  • 二、AOF持久化
    • 1、介绍以及测试
    • 2、优缺点
    • 3、AOF重写
    • 4、AOF重写存在的问题
  • 三、混合持久化
  • 四、RDB 和 AOF比较
  • 总结


前言

Redis作为缓存数据库,主要以快为目的,但是在有些公司,数据的第一入口便是使用Redis,那么这个时候数据的安全则是需要考虑的问题。Redis主要提供了两种持久化方式,基于内存快照的RDB方式和基于命令存储的AOF,他们各有优缺点,那么在Redis4.0之后还提供了新的持久化方式—混合持久化,Redis5.0之后默认是开启混合持久化的,下面我们将以这三种持久化做详细分析


一、RDB持久化

1、介绍以及测试

在默认情况下, Redis 将内存数据库快照保存在名字为 dump.rdb 的二进制文件中,配置文件中可修改配置

若不想用RDB方案,可以把 save "" 的注释打开,下面三个注释
#   save ""
save 900 5
save 300 10
save 60 10000

上面三个策略之间是或的关系,只要满足其中任何一个都可以,比如 save 900 5标识从Redis启动开始,每隔900秒,判断这900秒内是否有5次key被改动,那么则进行持久化。
测试:
将配置改成

save 60 5

Redis持久化之RDB+AOF+混合持久化实战演练_第1张图片
在测试过程中,发现当我们并没有完成策略,比如 60s内只完成一次key的改动,当我正常关闭Redis时候,也会持久化这一次的改动。后面经过查询发现是因为通过redis-cli SHUTDOWN这种命令方式去停掉redis,其实是一种安全退出的模式 ,这种模式退出redis会将内存中的数据立即生成一份完整的rdb快照保存到磁盘中,那么我们进行kill方式关闭Redis,发现在不符合策略的情况下,数据会丢失。

2、手动持久化方式bgsave

还可以手动执行命令生成RDB快照,进入redis客户端执行命令save或bgsave可以生成dump.rdb文件,每次命令执行都会将所有redis内存快照到一个新的rdb文件里,并覆盖原有rdb快照文件。
bgsave 子进程是由主线程 fork 生成的,主线程和 bgsave 子进程相互不影响。但是,如果主线程要修改一些数据,那么,这些数据就会被复制一份,生成该数据的副本。然后,bgsave 子进程会把这个副本数据写入 RDB 文件,而在这个过程中,主线程仍然可以直接修改原来的数据。

3、save与bgsave比较

命令 save bgsave
IO类型 同步 异步
是否阻塞redis其它命令 否(在生成子进程执行调用fork函数时会有短暂阻塞)
优点 不会消耗额外内存 不阻塞客户端命令

3、优缺点

使用RDB存储的优点是,存储文件小,Redis故障恢复快,性能较好(只会在完成策略时持久化)。但是缺点就是容易造成部分数据丢失。

二、AOF持久化

1、介绍以及测试

当RDB在未完成策略中宕机会产生数据丢失的风险,那么Redis还有另一种持久化方式-AOF,AOF 持久化,将修改的每一条指令记录进文件appendonly.aof。配置文件中可修改配置

#Redis 默认不开启,所以它采用日志的形式来记录每个写操作,并追加到文件中。Redis 重启的会根据日志文件
#的内容将写指令从前到后执行一次以完成数据的恢复工作,默认redis使用的是rdb方式持久化,这种方式在许多应用
#中已经足够用了。但是redis如果中途宕机,会导致可能有几分钟的数据丢失,根据save来策略进行持久化,
#Append Only File是另一种持久化方式,可以提供更好的持久化特性。Redis会把每次写入的数据在接收后都写
#appendonly.aof 文件。若开启rdb则将no改为yes
appendonly no

指定本地数据库文件名,默认值为 appendonly.aof
appendfilename "appendonly.aof"
 
#aof持久化策略的配置
#no表示不执行fsync,由操作系统保证数据同步到磁盘,速度最快
#always表示每次写入都执行fsync,以保证数据同步到磁盘
#everysec表示每秒执行一次fsync,可能会导致丢失这1s数据
appendfsync always
appendfsync everysec
appendfsync no

测试
将配置改成如下,关闭RDB,因为需要测试正常和非正常退出

save ""
appendonly yes
appendfilename appendonly.aof
appendfsync everyse

Redis持久化之RDB+AOF+混合持久化实战演练_第2张图片
查看appendonly.aof,发现命令已经存入aof文件中了,并且使用kill关闭Redis也不会导致数据丢失
Redis持久化之RDB+AOF+混合持久化实战演练_第3张图片

2、优缺点

AOF持久化解决了数据丢失的问题,以内存换数据安全,但是AOF持久化文件比RDB文件大,这样就会导致Redis在重启的时候加载持久化文件变得非常慢。

3、AOF重写

AOF文件里可能有太多没用指令,所以AOF会定期根据内存的最新数据生成aof文件,这样能解决部分RedisAOF文件过大的问题。

#设置允许重写的最小aof文件大小,避免了达到约定百分比但尺寸仍然很小的情况还要重写
auto-aof-rewrite-min-size 64mb

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

修改Redis配置如下,由于Redis5.0后默认开始混合持久化,所以我们需要手动关闭。

save ""
appendonly yes
appendfilename appendonly.aof
appendfsync everysec
auto-aof-rewrite-min-size 3k  #为了测试,将这个改为3K
auto-aof-rewrite-percentage 100

aof-use-rdb-preamble no #为了测试,关闭混合持久化

1、首先我们在命令框输入对同一个key进行修改
Redis持久化之RDB+AOF+混合持久化实战演练_第4张图片
此时查看appendonly.aof文件,发现每个命令都修改了
Redis持久化之RDB+AOF+混合持久化实战演练_第5张图片
当文件大小达到3K时,redis文件如下,进行了aof重写
Redis持久化之RDB+AOF+混合持久化实战演练_第6张图片
此时再次查看appendonly.aof文件,发现只剩下一个对这个key修改的命令。
在这里插入图片描述
当然AOF还可以手动重写,进入redis客户端执行命令bgrewriteaof重写AOF
注意,AOF重写redis会fork出一个子进程去做(与bgsave命令类似),不会阻塞redis处理正常命令

4、AOF重写存在的问题

如图展示的是AOFRW的实现原理。当AOFRW被触发执行时,Redis首先会fork一个子进程进行后台重写操作,该操作会将执行fork那一刻Redis的数据快照全部重写到一个名为temp-rewriteaof-bg-pid.aof的临时AOF文件中。
由于重写操作为子进程后台执行,主进程在AOF重写期间依然可以正常响应用户命令。因此,为了让子进程最终也能获取重写期间主进程产生的增量变化,主进程除了会将执行的写命令写入aof_buf,还会写一份到aof_rewrite_buf中进行缓存。在子进程重写的后期阶段,主进程会将aof_rewrite_buf中累积的数据使用pipe发送给子进程,子进程会将这些数据追加到临时AOF文件中。
当主进程承接了较大的写入流量时,aof_rewrite_buf中可能会堆积非常多的数据,导致在重写期间子进程无法将aof_rewrite_buf中的数据全部消费完。此时,aof_rewrite_buf剩余的数据将在重写结束时由主进程进行处理。
当子进程完成重写操作并退出后,主进程会在backgroundRewriteDoneHandler 中处理后续的事情。首先,将重写期间aof_rewrite_buf中未消费完的数据追加到临时AOF文件中。其次,当一切准备就绪时,Redis会使用rename 操作将临时AOF文件原子的重命名为server.aof_filename,此时原来的AOF文件会被覆盖。至此,整个AOFRW流程结束。
Redis持久化之RDB+AOF+混合持久化实战演练_第7张图片

  • 内存开销
    在AOF重写期间,主进程会将fork之后的数据变化写进aof_rewrite_buf中,aof_rewrite_buf和aof_buf中的内容绝大部分都是重复的,因此这将带来额外的内存冗余开销。带来的内存开销有可能导致Redis内存突然达到maxmemory限制,从而影响正常命令的写入,甚至会触发操作系统限制被OOM Killer杀死,导致Redis不可服务
  • CPU 开销
    (1):主进程需要花费CPU时间向aof_rewrite_buf写数据,并使用eventloop事件循环向子进程发送aof_rewrite_buf中的数据
    (2):在子进程执行重写操作的后期,会循环读取pipe中主进程发送来的增量数据,然后追加写入到临时AOF文件
    (3):在子进程完成重写操作后,主进程会进行收尾工作。其中一个任务就是将在重写期间aof_rewrite_buf中没有消费完成的数据写入临时AOF文件。如果aof_rewrite_buf中遗留的数据很多,这里也将消耗CPU时间
  • 磁盘IO开销
    在AOF重写期间,主进程除了会将执行过的写命令写到aof_buf之外,还会写一份到aof_rewrite_buf中。aof_buf中的数据最终会被写入到当前使用的旧AOF文件中,产生磁盘IO。同时,aof_rewrite_buf中的数据也会被写入重写生成的新AOF文件中,产生磁盘IO。因此,同一份数据会产生两次磁盘IO。

在Redis 7.0 (已发布RC1) 中Multi Part AOF(下文简称为MP-AOF,本特性由阿里云数据库Tair团队贡献)中优化了AOF重写的性能问题。

三、混合持久化

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

aof-use-rdb-preamble yes # redis5.0后默认开启

在这里插入图片描述
如果开启了混合持久化,触发机制是AOF在重写所以一定要开启AOF持久化。在AOF在重写时,不再是单纯aof文件中的命令进行重写,而是将重写这一刻之前的内存做一次整体的RDB dump处理,并且将RDB快照内容和增量的AOF修改内存数据的命令存在一起,都写入新的AOF临时文件,等到重写完会对临时的AOF文件进行改名,覆盖原有的AOF文件,完成新旧两个AOF文件的替换。
继续测试,配置如下
Redis持久化之RDB+AOF+混合持久化实战演练_第8张图片
当AOF文件达到3K时,redis日志如下图
Redis持久化之RDB+AOF+混合持久化实战演练_第9张图片
再次查看appendonly.aof文件,发现文件内容变成 RDB+AOF的格式
Redis持久化之RDB+AOF+混合持久化实战演练_第10张图片

四、RDB 和 AOF比较

命令 RDB AOF
启动优先级
文件大小
恢复速度
数据安全 数据可能丢失 根据策略觉得,可以相等较高

总结

以上就是针对Redis持久化进行讲解以及测试,大家在使用过程中根据实际情况进行配置和选择。如有问题,请大家多多评论

你可能感兴趣的:(Redis,redis,缓存,数据库,redis持久化,redis混合持久化)