乐趣区

关于redis:Redis的持久化数据备份方案和数据恢复

文章首发:Redis 的长久化、数据备份计划和数据恢复

redis 的长久化

RDB 长久化

redis 会 fork 创立一个子过程来进行长久化。将数据写进一个临时文件,长久化完结之后会替换上一个长久化好的 RDB 文件。在这期间 redis 主过程不会参加长久化,以保障 redis 的高性能。

触发:

  1. 客户端在执行 shutdown 命令时,如果没有开启 AOF 长久化,那么就会触发 RDB 的长久化。
  2. 在 redis 的配置文件中有以下默认配置。在一下的条件成立时,就会触发 RDB 的长久化,而且是应用 save 命令实现的。然而 save 命令会阻塞主过程。个别应用 bgsave 命令,会 fork 出一个子过程进行长久化操作。

    save 900 1     #after 900 sec (15 min) if at least 1 key changed
    save 300 10    #after 300 sec (5 min) if at least 10 keys changed
    save 60 10000  #after 60 sec if at least 10000 keys changed
  3. 执行 flushall 命令清空内存中的数据时,同时触发长久化,清空磁盘。

长处和毛病

长处:数据恢复比拟快,适宜大规模的数据恢复,适宜当作冷备的计划。

毛病:如果是忽然宕机,失落的数据比拟多。数据量大时,长久化生成快照 RDB 文件会影响 redis 的性能。

AOF 长久化

开启了 AOF 之后,会将所有命令追加到 AOF 缓冲区中,依据对应的写入策略写入到磁盘的 AOF 的长久化文件中。能够说就是 redis 的一个日志文件,外面记录的是 redis 的写操作。然而因为记录的是一条条命令,AOF 文件会收缩的很快,达到一定量的时候,就会触发 rewrite 操作,重写 AOF 文件,来达到压缩的目标(fork 子过程来实现)。

redis 应用单线程响应命令,如果每次写 AOF 文件命令都间接追加到硬盘,那么性能瓶颈齐全取于以后硬盘负载。先写入缓冲区 aof_buf 中,还有另一益处,redis 能够提供多种缓冲区同步硬盘的策略,在性能和安全性方面做出衡量。

触发:

  1. redis 的配置文件中默认是没有开启 AOF 的,要开启在配置文件中关上即可appendonly no —>appendonly yes。也能够在 redis 曾经运行时设置:CONFIG SET appendonly yes,不过这样当 redis 重启时,设置会生效。
  2. 配置的写入策略触发。

    1. appendfsync everysec(默认):每秒同步一次命令到 AOF 长久化文件中,效率很高,可能会失落 1 秒的数据。
    2. appendfsync no:从不同步,只需将数据交给操作系统即可。更快,更不平安的办法。通常,Linux 将应用此配置每 30 秒刷新一次数据,但这取决于内核的准确调整。
    3. appendfsync always:每次触发数据变更的时候立刻追加到 AOF 文件中,效率很低,然而很平安。

重写机制:

  1. 默认配置。比如说上一次 AOF rewrite 之后,是 128mb。而后就会接着 128mb 持续写 AOF 的日志,如果发现增长的比例,超过了之前的 100%,256mb,就可能会去触发一次 rewrite。然而此时还要去跟 min-size,64mb 去比拟,256mb > 64mb,才会去触发 rewrite。

    因为 AOF 文件的重写会 fork 出一个子过程进行重写,为了缩小重写次数须要调大上面的参数,然而都是要基于本身应用的 redis 的寄存的数据量来决定。

    auto-aof-rewrite-percentage 100
    auto-aof-rewrite-min-size 64mb

长处和毛病:

长处:以更好的爱护数据不失落,个别 AOF 会每隔 1 秒(默认的同步策略),通过一个后盾线程执行一次 fsync 操作,最多失落 1 秒钟的数据。

AOF 日志文件以 append-only 模式写入,所以没有任何磁盘寻址的开销,写入性能十分高,而且文件不容易破损,即便文件尾部破损,也很容易修复(应用 redis 提供的工具能够修复:redis-check-aof --fix)。

日志文件即便过大的时候,呈现后盾重写操作,也不会影响客户端的读写。因为在 rewrite log 的时候,会对其中的领导进行压缩,创立出一份须要复原数据的最小日志进去。再创立新日志文件的时候,老的日志文件还是照常写入。当新的 merge 后的日志文件 ready 的时候,再替换新老日志文件即可。

AOF 日志文件的命令通过十分可读的形式进行记录,这个个性非常适合做灾难性的误删除的紧急复原。比方某人不小心 用 flushall 命令清空了所有数据 ,只有这个时候后盾rewrite 还没有产生,那么就能够立刻 拷贝 AOF 文件 将最初一条 flushall 命令给删了,而后再将该 AOF 文件放回去,就能够通过复原机制,主动复原所有数据

毛病:对于同一份数据来说,AOF 日志文件通常比 RDB 数据快照文件更大。

AOF 开启后,反对的写 QPS 会比 RDB 反对的写 QPS 低,因为 AOF 个别会配置成每秒 fsync 一次日志文件,当然,每秒一次 fsync,性能也还是很高的。

相似 AOF 这种较为简单的基于命令日志 /merge/ 回放的形式,比基于 RDB 每次长久化一份残缺的数据快照文件的形式,更加软弱一些,容易有 bug。不过 AOF 就是为了防止 rewrite 过程导致的 bug,因而每次 rewrite 并不是基于旧的指令日志进行 merge 的,而是基于过后内存中的数据进行指令的从新构建,这样健壮性会好很多。

RDB 和 AOF 到底该如何抉择

  1. 不要仅仅应用 RDB,因为那样会导致你失落很多数据
  2. 也不要仅仅应用 AOF,因为那样有两个问题,第一,你通过 AOF 做冷备,没有 RDB 做冷备,来的复原速度更快; 第二,RDB 每次简略粗犷生成数据快照,更加强壮,能够防止 AOF 这种简单的备份和复原机制的 bug
  3. 综合应用 AOF 和 RDB 两种长久化机制,用 AOF 来保证数据不失落,作为数据恢复的第一抉择; 用 RDB 来做不同水平的冷备,在 AOF 文件都失落或损坏不可用的时候,还能够应用 RDB 来进行疾速的数据恢复

所以说成年人,全都要!

AOF 和 RDB 同时工作:

  1. 如果 RDB 在执行 snapshotting 操作,那么 redis 不会执行 AOF rewrite; 如果 redis 再执行 AOF rewrite,那么就不会执行 RDB snapshotting
  2. 如果 RDB 在执行 snapshotting,此时用户执行 BGREWRITEAOF 命令,那么等 RDB 快照生成之后,才会去执行 AOF rewrite
  3. 同时有 RDB snapshot 文件和 AOF 日志文件,那么 redis 重启的时候,会优先应用 AOF 进行数据恢复,因为其中的日志更残缺

redis 长久化文件加载流程

  1. 首先是会去判断是否开启了 AOF,如果存在存在 AOF 文件,则间接加载 AOF 文件
  2. 如果找不到 AOF 文件,则间接启动,不会加载 RDB 文件
  3. 如果没有开启 AOF,会去加载 RDB 文件,通过 RDB 复原数据

数据备份计划

  1. 写 crontab 定时调度脚本去做数据备份
  2. 每小时都 copy 一份 rdb 的备份,到一个目录中去,仅仅保留最近 48 小时的备份
  3. 每天都保留一份当日的 rdb 的备份,到一个目录中去,仅仅保留最近 1 个月的备份
  4. 每次 copy 备份的时候,都把太旧的备份给删了(是否删除旧的备份,看具体情况而定)
  5. 每天晚上将以后服务器上所有的数据备份,发送一份到近程的云服务器 (用于寄存备份即可,也能够寄存在本地) 下来。

每小时备份一次:redis_rdb_backup_hourly.sh

#!/bin/sh 

cur_date=`date +%Y%m%d%k`
rm -rf /usr/local/redis/snapshotting/$cur_date
mkdir /usr/local/redis/snapshotting/$cur_date
# 备份寄存本地
cp /var/redis/6379/dump.rdb /usr/local/redis/snapshotting/$cur_date
# 备份发送到备份服务器,留神免明码登录
# scp -rq /var/redis/6379/dump.rdb root@192.168.129.100:/opt

# 删除最近 48 小时的 rdb 文件
del_date=`date -d -48hour +%Y%m%d%k`
rm -rf /usr/local/redis/snapshotting/$del_date

每小时执行一次该脚本:0 0 * * * ? sh /usr/local/redis/shell/redis_rdb_backup_hourly.sh

每天备份一次:redis_rdb_backup_daily.sh

#!/bin/sh 

cur_date=`date +%Y%m%d`
rm -rf /usr/local/redis/snapshotting/$cur_date
mkdir /usr/local/redis/snapshotting/$cur_date
cp /var/redis/6379/dump.rdb /usr/local/redis/snapshotting/$cur_date

del_date=`date -d -1day +%Y%m%d`
rm -rf /usr/local/redis/snapshotting/$del_date

每天执行一次备份脚本:0 0 0 * * ? sh /usr/local/redis/shell/redis_rdb_backup_daily.sh

数据恢复计划

(1)如果是 redis 过程挂掉,那么重启 redis 过程即可,间接基于 AOF 日志文件复原数据

(2)如果是 redis 过程所在机器挂掉,那么重启机器后,尝试重启 redis 过程,尝试间接基于 AOF 日志文件进行数据恢复。AOF 没有破损,也是能够间接基于 AOF 复原的。AOF append-only,程序写入,如果 AOF 文件破损,那么用 redis-check-aof fix

(3)如果 redis 以后最新的 AOF 和 RDB 文件呈现了失落 / 损坏,那么能够尝试基于该机器上以后的某个最新的 RDB 数据正本进行数据恢复。

以后最新的 AOF 和 RDB 文件都呈现了失落 / 损坏到无奈复原,个别不是机器的故障,人为。那就把破损的文件给删除了。去备份服务器找到 RDB 最新的一份备份,小时级的备份能够了,小时级的必定是最新的,copy 到 redis 外面去,就能够复原到某一个小时的数据

进行 redis,敞开 aof,拷贝 rdb 备份,重启 redis,确认数据恢复,间接在命令行热批改 redis 配置,关上 aof,这个 redis 就会将内存中的数据对应的日志,写入 aof 文件中

此时 aof 和 rdb 两份数据文件的数据就同步了

redis config set 热批改配置参数,可能配置文件中的理论的参数没有被长久化的批改,再次进行 redis,手动批改配置文件,关上 aof 的命令,再次重启 redis

(4)如果以后机器上的所有 RDB 文件全副损坏,那么从近程的云服务上拉取最新的 RDB 快照回来复原数据

(5)如果是发现有重大的数据谬误,比方某个小时上线的程序一下子将数据全副净化了,数据全错了,那么能够抉择某个更早的工夫点,对数据进行复原

举个例子,12 点上线了代码,发现代码有 bug,导致代码生成的所有的缓存数据,写入 redis,全副错了

找到一份 11 点的 rdb 的冷备,而后依照下面的步骤,去复原到 11 点的数据。

退出移动版