redis
提供了数据持久化的方式,提供数据持久化的意义在于数据的恢复、生产环境下的灾难恢复。
本文将会围绕redis
的两种持久化方式对于它们的运行机制、注意事项、备份方案以及基于灾难恢复的场景下的数据恢复方案。
RDB持久化会对redis
中的数据进行周期性的持久化,生成一份快照文件,存放在配置文件声明的目录下面的dump.rdb
文件。在redis
配置文件中可以通过配置dir
属性来指定持久化文件存放目录。默认情况下RDB
持久化是打开的,可以在配置文件中找到如下内容:
save 900 1
save 300 10
save 60 10000
上述命令之的是如果900秒内有1个key
发生了变化,生成一份快照文件,如果再300秒内有10个key
发生了改变,生成一份快照文件,如果在60秒内有10000个key
发生了改变,生成一份快照文件。
save
可以设置多个,就是多个snapshotting
检查点,每到一个检查点,就会去检查一下,是否有指定的key数量发生变化,如果有就生成一个新的dump.rdb
文件
也可以通过save
或者bgsave
命令同步或异步指定rdb快照生成。
redis
根据配置自己尝试生成rdb
快照文件fork
一个子进程出来rdb
快照文件中rdb
快照文件的生成之后,就替换之前旧的快照文件dump.rdb
每次生成一个快照,都会覆盖之前的旧文件。
AOF持久化会记录服务器执行的所有写操作命令,并在redis
重启的时候,通过回访AOF
文件来还原数据集,文件使用append-only
的默认,所有操作都会追加到文件的末尾。当AOF
文件体积超出保存数据集状态的情况下,会进行一个重写(rewrite
)操作,确保文件不会太大。通常情况下,AOF
文件保存的数据及会比RDB
文件保存的数据集更完整。
默认情况下AOF持久化是关闭的,通过以下配置开启AOF持久化
appendonly yes
开启后,会在文件存储目录下面生成一个appendpnly.aof
文件,开启了AOF
之后,redis
重启的时候,会优先通过AOF
进行数据恢复。
打开AOF持久化机制之后,redis
每次接收到一条写命令,就会写入日志文件中,当然是先写入os cache
的,然后每隔一定时间再fsync
一下
可以通过配置以下内容来配置AOF
的fsync
策略:
appendfsync everysec
这个属性有3个值可以配置:
always
每写入一条数据,立即将这个数据对应给的写日志fsync
到磁盘上去,性能会变得很差,但是可以确保说每一条数据都不会丢失everysec
每秒将os cache
中的数据fsync
到磁盘,这个最常用,生产环境下一般都使用这种策略,性能很高。no
仅仅负责将数据写到os cache
就可以了,不进行fsync
等待操作系统对这些数据写入磁盘,这种策略,会让我们的数据不可控,因为无法预知操作系统什么时候会把数据刷到磁盘。rewrite
redis中的数据是有限的,很多数据可能会自动过期,也有可能会被用户删除,但是这些操作都会被AOF
文件记录下来,所有有可能存在AOF
文件越来越大的情况,意思就是说,重建数据集根本不需要执行所有AOF
记录的命令,为了处理这种情况,会有一种rewrite
策略,在redis 2.4
之前是需要手动执行BGREWRITEAOF
命令来进行重写AOF
文件,redis 2.4
版本之后提供了自动rewrite
的操作。我们可以配置rewrite
的策略
auto-aof-rewrite-percentage 100
auto-aof-rewrite-min-size 64mb
这两个参数的意思是,最少AOF
文件需要达到64mb就会进行重写,重写了之后,当检测到当前的AOP
文件增长幅度大于100%,也就是64mb,即当前的AOF
文件大小为128mb的时候,就会自动触发对AOF
进行重写操作。
rewrite
的过程如下:
redis fork
一个子进程AOF
文件中写入日志redis
主进程,接收到client
的写操作,在内存中写入日志,同时新的日志也继续写入旧的AOF
文件redis
主进程将内存中的新日志再次追加到新的AOF
文件中如果AOF
文件破损了,可以使用redis-check-aof --fix filename
命令来修复破损的AOF
文件
RDB
会生成多个数据文件,每个数据文件都表示了某个时刻中redis
的数据,这种多数据文件的方式,非常适合做冷备,可以将定时定期RDB
文件通过加密后传输到某些云服务上保存,RDB
非常适用于灾难恢复,同时在数据集非常的的情况下,恢复速度比AOF
更快。RDB
在做数据持久化的时候,通过fork
一个子进程来工作,父进程无需进行任何IO
操作。
在redis
故障的时候,RDB
无法尽量避免数据丢失,如果需要在故障的时候尽可能减少数据丢失,那么AOF
更适合,一般来说,RDB
保存数据有可能5分钟或者更长时间才做一次,这个时候如果redis
故障了,那么可能丢失将近5分钟的数据,同时,如果数据集特别大的时候,fork
会非常耗时,如果服务器资源比较紧张的情况下,可能会导致对客户端暂停数毫秒甚至数秒的服务。
AOF
可以更好的保障数据不丢失,默认情况下AOF
会每隔一秒,通过一个后台线程执行一次fsync
操作,所以最多只会丢失1秒的数据,AOF
日志文件已append-only
模式写入,没有任何磁盘寻址的开销,性能非常高,即使文件损坏了。也可以通过redis
提供的工具进行修复。当AOF
文件过大的时候,会在后台进行重写,确保日志文件不会过大。
同一份数据,通常AOF
会比RDB
文件更大,AOF
开启后,支持的写QPS
会比RDB
的低,因为AOF
一般设置为每秒fsync
一次日志文件,其次在数据恢复的时候,会比较慢,做冷备不太适合。
RDB
方式,因为那样有可能会导致丢失较多数据AOF
方式,因为使用AOF
进行数据恢复速度较慢,而且使用RDB
生成快照的方式更叫健壮,可以避免AOF
这种复杂的备份和恢复机制的bug
AOF
和RDB
两种持久化机制,用AOF
保证数据不丢失,作为数据恢复的第一选择,用RDB
来做不同程度的冷备,在AOF
文件丢失或者不可用的情况下,可以使用RDB来进行数据恢复。RDB
在执行snapshotting
操作,那么redis
不会执行AOF
rewrite
,如果redis
在执行AOF
rewrite
,则不会执行RDB
的snapshotting
RDB
在执行snapshotting
,此时用户执行BGREWRITEAOF
命令,那么会等待RDB
执行完毕,再去至执行AOF
rewrite
RDB
snapshot
文件和AOF
日志文件,那么redis
重启的时候,会优先使用AOF
进行数据恢复,因为其中的日志更完整crontab
定时调度脚本做数据备份,每小时备份一次rdb
文件,保存最近48小时的数据rdb
文件,保留最近一个月下面是一份示例的代码:
redis_rdb_copy_hourly.sh
#!/bin/sh
# 当前小时
cur_date=`date +%Y%m%d%k`
# 移除备份目录
rm -rf /xxx/$cur_date
# 创建备份目录
mkdir /xxx/$cur_date
# 复制rdb文件到辈分目录
cp /xxx/dump.rdb /xxx/$cur_date
#删除48小时之前的备份文件
del_date=`date -d -48hour +%Y%m%d%k`
rm -rf /xxx/$del_date
redis_rdb_copy_daily.sh
#!/bin/sh
cur_date=`date +%Y%m%d`
rm -rf /xxx/$cur_date
mkdir /xxx/$cur_date
cp /xxx/dump.rdb /xxx/$cur_date
# 删除旧得备份数据
del_date=`date -d -1month +%Y%m%d`
rm -rf /usr/local/redis/snapshotting/$del_date
redis
进程挂掉,那么重启redis
进程即可,直接基于AOF
日志文件恢复数据redis
进程所在机器挂掉,那么重启机器后,尝试重启redis
进程,尝试直接基于AOF
日志文件进行数据恢复,如果AOF
文件破损,那么用redis-check-aof fix
命令修复redis
当前最新的AOF和RDB文件出现了丢失/损坏,那么可以尝试基于该机器上当前的某个最新的RDB
数据副本进行数据恢复在数据完全丢失的情况下,基于RDB
冷备,完美恢复数据方案:
redis
AOF
RDB
备份文件redis
redis-cli
开启AOF
(redis config set
)AOF
和RDB
两份数据文件数据同步redis
AOF
redis
AOF
文件,然后拷贝RDB
文件到持久化目录就启动redis
的话,如果不关闭AOF
,每次启动redis
会读取AOF
文件,这个时候AOF
文件是没有的,redis
会自动生成一个空的AOF
文件,然后加载到内存中,同时会基于当前内存数据(空的)生成一份RDB
文件,会覆盖掉备份的RDB
文件。如果当前机器上的所有RDB
文件全部损坏,那么从远程的云服务上拉取最新的RDB
快照回来恢复数据
如果是发现有重大的数据错误,比如某个小时上线的程序一下子将数据全部污染了,数据全错了,那么可以选择某个更早的时间点,对数据进行恢复
本文介绍了redis
的两种持久化方式机制以及它们的优缺点,同时介绍了redis
数据的备份与恢复方案。