欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

Redis持久化 - AOF持久化(二)

程序员文章站 2022-05-20 21:22:04
...

一、Redis持久化概述

持久化的功能:Redis是内存数据库,数据都是存储在内存中,为了避免进程退出导致数据的永久丢失,需要定期将Redis中的数据以某种形式(数据或命令) 从内存保存到硬盘。 当下次Redis重启时,利用持久化文件实现数据恢复。除此之外,为了进行灾难备份,可以将持久化文件拷贝到一个远程位置。Redis持久化 分为RDB持久化和AOF持久化前者将当前数据保存到硬盘,后者则是将每次执行的写命令保存到硬盘

2.AOF持久化

AOF(append only file)持久化:与RDB存储某个时刻的快照不同,AOF持久化方式会记录客户端对服务器的每一次写操作命令到日志当中,并将这些写操作 以Redis协议追加保存到以后缀为aof文件末尾

RDB 持久化默认是关闭的,具体查看redis.conf配置文件:
Redis持久化 - AOF持久化(二)

  • 使用AOF

开启 AOF 功能需要设置配置:appendonly yes,默认不开启。
AOF 文件名通过 appendfilename 配置设置,默认文件名是 appendonly.aof。
保存路径同 RDB 持久化方式一致,通过 dir 配置指定

  • 配置说明

appendonly yes #启用aof持久化

持久化方式:

  1. appendfsync always #每次收到写命令就立即强制写入磁盘,最慢的大概只有几百的TPS,但是保证完全 的持久化,不推荐使用

  2. appendfsync everysec #每秒钟强制写入磁盘一次,在性能和持久化方面做了很好的折中,推荐

  3. appendfsync no #完全依赖os,性能最 好,持久化没保证,Redis不会主动调用fsync去将AOF日志内容同步到磁盘,所以这一切就完全依赖于操作系统的调试了。对大多数Linux操作系统,是每30秒进行 一次fsync,将缓冲区中的数据写到磁盘上。

  • 工作流程说明

Redis持久化 - AOF持久化(二)

流程如下:

  1. 所有的写入命令会追加到 aof_buf(缓冲区)中。

  2. AOF 缓冲区根据对应的策略向硬盘做同步操作。

  3. 随着 AOF 文件越来越大,需要定期对 AOF 文件进行重写,达到压缩的目的。

  4. 当 Redis 服务器重启时,可以加载 AOF 文件进行数据恢复。

  • 重写机制说明

AOF将客户端的每一个写操作都追加到aof文件末尾,随着命令不断写入 AOF,文件会越来越大,为了解决这个问题,Redis 引入 AOF 重写机制压缩文 件体积。

AOF 文件重写是把 Redis 进程内的数据转化为写命令同步到新 AOF 文件的过程。

比如:
多条写命令可以合并为一个,如:lpush list a、lpush list b、lpush list c 可以转化为:lpush list a b c。 AOF 重写降低了文件占用空间,除此之外,另一个目的是:更小的 AOF 文件可以更快地被 Redis 加载。

  • 触发机制

AOF 重写过程可以手动触发和自动触发:

  1. 手动触发:直接调用 bgrewriteaof 命令。

    127.0.0.1:6379> bgrewriteaof
    Background append only file rewriting started
    
  2. 自动触发:根据 auto-aof-rewrite-min-size和auto-aof-rewrite-percentage 参数确定自动触发时机。

    • auto-aof-rewrite-min-size:表示运行 AOF 重写时文件最小体积,默认为 64MB。

    • auto-aof-rewrite-percentage:代表当前 AOF 文件空间(aof_current_size)和上一次重写后 AOF 文件空间(aof_base_size)的比值

      示例: 
      	auto-aof-rewrite-percentage:100 
      	auto-aof-rewrite-min-size:64mb
      	默认配置是当AOF文件大小是上次rewrite后大小的一倍且文件大于64M时触发
      

截图:
Redis持久化 - AOF持久化(二)

  • 当触发 AOF 重写时,内部做了哪些事呢?下面介绍下它的运行流程

Redis持久化 - AOF持久化(二)
流程:

1.执行 AOF 重写请求。 如果当前进程正在执行 AOF 重写,请求不执行并返回如下响应: ERR Background append only file rewriting already in progress

2.父进程执行 fork 创建子进程,开销等同于 bgsave 过程。

3.1 主进程 fork 操作完成后,继续响应其他命令。所有修改命令依然写入 AOF 缓冲区并根据 appendfsync 策略同步到硬盘,保证原有 AOF 机制正确 性。

3.2 由于 fork 操作运用写时复制技术,子进程只能共享 fork 操作时的内存数据。由于父进程依然响应命令,Redis 使用“AOF 重写缓冲区”保存这部 分新数据,防止新 AOF 文件生成期间丢失这部分数据。

4.子进程根据内存快照,按照命令合并规则写入到新的 AOF 文件。每次批量写入硬盘数据量由配置 aof-rewrite-incremental-fsync 控制,默认为 32MB,防止单 次刷盘数据过多造成硬盘阻塞。

4.1 新 AOF 文件写入完成后,子进程发送信号给父进程,父进程更新统计信息,具体见 info persistence 下的 aof_*相关统计。
4.2 父进程把 AOF 重写缓冲区的数据写入到新的 AOF 文件。
4.3 使用新 AOF 文件替换老文件,完成 AOF 重写。

  • AOF注意事项

    AOF文件损坏

在写入aof日志文件时,如果Redis服务器宕机,则aof日志文件文件会出格式错误,在重启Redis服务器时,Redis服务器会拒绝载入这个aof文件, 可以通过命令修复aof并恢复数据

恢复命令:
redis-check-aof --fix file.aof

demo:
[aaa@qq.com src]# ./redis-check-aof --fix eppendonly.aof
  • AOF的优点

1.AOF可以设置 完全不同步、每秒同步、每次操作同,默认是每秒同步。因为AOF是操作指令的追加,所以可以频繁的大量的同步

2.AOF文件是一个值追加日志的文件,即使服务宕机为写入完整的命令,也可以通过redis-check-aof工具修复这些问题。

3.如果AOF文件过大,Redis会在后台自动地重写AOF文件。重写后会使AOF文件压缩到最小所需的指令集。

4.AOF文件是有序保存数据库的所有写入操作,易读,易分析。即使如果不小心误操作数据库,也很容易找出错误指令,恢复到某个数据节点。例如不 小心FLUSHALL,可以非常容易恢复到执行命令之前。

  • AOF的缺点

1、相同数据量下,AOF的文件通常体积会比RDB大。因为AOF是存指令的,而RDB是所有指令的结果快照。但AOF在日志重写后会压缩一些空间。

2、在大量写入和载入的时候,AOF的效率会比RDB低。因为大量写入,AOF会执行更多的保存命令,载入的时候也需要大量的重执行命令来得到最后的结 果。RDB对此更有优势。

3.重启加载的选择

AOF 和 RDB 文件都可以用于服务器重启时的数据恢复

服务器重启数据恢复流程:
Redis持久化 - AOF持久化(二)

  • 持久化的选择

在实际生产环境中,根据数据量、应用对数据的安全要求、预算限制等不同情况,会有各种各样的持久化策略;如完全不使用任何持久化、使用RDB或 AOF的一种,或同时开启RDB和AOF持久化等。此外,持久化的选择必须与Redis的主从策略一起考虑,因为主从复制与持久化同样具有数据备份的功能, 而且主机master和从机slave可以独立的选择持久化方案。

===========================================
面分场景来讨论持久化策略的选择,下面的讨论也只是作为参考,实际方案可能更复杂更具多样性。

  1. 如果Redis中的数据完全丢弃也没有关系(如Redis完全用作DB层数据的cache),那么无论是单机, 还是主从架构,都可以不进行任何持久化。

  2. 在单机环境下(对于个人开发者,这种情况可能比较常见),如果可以接受十几分钟或更多的数据丢失,选择RDB对Redis的性能更加有利; 如果只能接受秒级别的数据丢失,应该选择AOF。

  3. 但在多数情况下,我们都会配置主从环境,slave的存在既可以实现数据的热备,也可以进行读写分离分担Redis读请求, 以及在master宕掉后继续提供服务。

    在这种情况下的做法是:

    master:完全关闭持久化(包括RDB和AOF),这样可以让master的性能达到最好;

    slave:关闭RDB,开启AOF(如果对数据安全要求不高,开启RDB关闭AOF也可以),并定时对持久化文件进行备份(如备份到其他文件夹,并 标记好备份的时间);然后关闭AOF的自动重写,然后添加定时任务,在每天Redis闲时(如凌晨12点)调用bgrewriteaof。

    为什么开启了主从复制,可以实现数据的热备份,还需要设置持久化呢?
    因为在一些特殊情况下,主从复制仍然不足以保证数据的安全,
    例如:

    master和slave进程同时停止:考虑这样一种场景,如果master和slave在同一个机房,则一次停电事故就可能导致master和slave机器同时关 机,Redis进程停止;如果没有持久化,则面临的是数据的完全丢失。

    master误重启:考虑这样一种场景,master服务因为故障宕掉了,如果系统中有自动拉起机制(即检测到服务停止后重启该服务)将master自 动重启,由于没有持久化文件,那么master重启后数据是空的, slave同步数据也变成了空的;

    如果master和slave都没有持久化,同样会面临数据的完全丢失。需要注意的是,即便是使用了哨兵进行自动的主从切换, 也有可能在哨兵轮询到master之前,便被自动拉起机制重启了。因此,应尽量避免“自动拉起机制”和“不做持久化”同时出现。

    如果需要最大限度需要数据无损:
    建议master开启aof,slave开启aof,开启aof需要cpu和磁盘性能保障。开启aof建议fsync同步刷盘使用everysec,自定义脚本在应用空闲时定时 做bgrewrite

  4. 异地灾备:上述讨论的几种持久化策略,针对的都是一般的系统故障,如进程异常退出、宕机、断电等,这些故障不会损坏硬盘。但是对于一些可 能导致硬盘损坏的灾难情况,如火灾地震,就需要进行异地灾备。

    例如对于单机的情形,可以定时将RDB文件或重写后的AOF文件,通过scp拷贝到远程机器,如阿里云;对于主从的情形,可以定时在master上执行 bgsave,然后将RDB文件拷贝到远程机器, 或者在slave上执行bgrewriteaof重写AOF文件后,将AOF文件拷贝到远程机器上。

    一般来说,由于RDB文件文件小、恢复快,因此灾难恢复常用RDB文件;异地备份的频率根据数据安全性的需要及其它条件来确定,但最好不要低于 一天一次。

注意:

  1. RDB虽然可以通过bgsave指令后台保存快照,但fork()子进程是有开销的,在内存数据集较大的情况下会占用很长的cpu时间,fork新进程时 这个复制是需要时间的,在服务器结点上测试,35G的数据bgsave瞬间会阻塞200ms以上,一般建议Redis使用内存不超过20g。

  2. I/O消耗的问题 线上是在Slave节点开启rdb持久化,磁盘性能一般,1.2g的rdb文件持久化一分钟一次, 一次大概耗时30s左右,所以rdb的频率也不能太频繁,需要根据情况做好配置。

  3. AOF是追加写命令到aof文件的方式,优点是可以基本做到数据无损,缺点是文件增长较快,需要间歇性bgrewrite,bgrewrite也是一个既耗cpu又耗 磁盘IO的操作, 单cpu利用率最高可达100%,一般建议找几个空闲时段设置脚本来做bgrewrite。

  • 持久化配置方案
  1. 企业级的持久化的配置策略

    save 60 10000:如果你希望尽可能确保说,RDB最多丢1分钟的数据,那么尽量就是每隔1分钟都生成一个快照,低峰期,数据量很少,也没必要 10000->生成RDB,1000->RDB,这个根据你自己的应用和业务的数据量,你自己去决定

    AOF一定要打开,fsync,everysec
    auto-aof-rewrite-percentage 100: 就是当前AOF大小膨胀到超过上次100%,上次的两倍
    auto-aof-rewrite-min-size 64mb: 根据你的数据量来定,16mb,32mb

  2. 数据备份方案

    RDB非常适合做冷备,每次生成之后,就不会再有修改了
    数据备份方案
    1. 写crontab定时调度脚本去做数据备份
    2. 每小时都copy一份rdb的备份,到一个目录中去,仅仅保留最近48小时的备份
    3. 每天都保留一份当日的rdb的备份,到一个目录中去,仅仅保留最近1个月的备份
    4. 每次copy备份的时候,都把太旧的备份给删了
    5. 每天晚上将当前服务器上所有的数据备份,发送一份到远程的云服务上去【crontab】

  • AOF常用配置总结

    appendonly no:是否开启AOF

    appendfilename “appendonly.aof”:AOF文件名

    dir ./:RDB文件和AOF文件所在目录

    appendfsync everysec:fsync持久化策略

    no-appendfsync-on-rewrite no:AOF重写期间是否禁止fsync;如果开启该选项,可以减轻文件重写时CPU和硬盘的负载(尤其是硬盘),但是可能会丢 失AOF重写期间的数据;需要在负载和安全性之间进行平衡

    auto-aof-rewrite-percentage 100:文件重写触发条件之一

    auto-aof-rewrite-min-size 64mb:文件重写触发提交之一

    aof-load-truncated yes:如果AOF文件结尾损坏,Redis启动时是否仍载入AOF文件

相关标签: redis