Redis 是一个支持持久化的内存数据库,也就是说 Redis 可以将内存中的数据同步到硬盘,来实现持久化。
Redis 提供了不同级别的持久化方式:
- RDB持久化方式:在指定的时间间隔能对你的数据进行快照存储。
- AOF持久化方式:记录每次对服务器写的操作,当服务器重启的时候会重新执行这些命令来恢复原始的数据
RDB持久化
RDB是在某个时间点将数据写入一个临时文件,持久化结束后,用这个临时文件替换上次持久化的文件,达到数据恢复。 redis默认持久化的方式
这里说的这个执行数据写入到临时文件的时间点是可以通过配置来自己确定的,通过配置redis在n秒内如果超过m个key被修改则执行一次RDB操作。这个操作就类似于在这个时间点来保存一次Redis的所有数据,一次快照数据。所以这个持久化方法也通常叫做snapshots。
RDB生成方式
- 指向命令手动生成
有两个Redis命令可以生成RDB文件,一个是SAVE,另一个是BGSAVE。
-
SAVE 命令会阻塞Redis服务器进程,直到RDB文件创建完毕为止,在服务器阻塞期间,服务器不能处理任何的进程
-
BGSAVE会派出一个子进程,然后由子进程负责创建RDB文件,服务器进程(父进程)继续处理命令请求,父进程无须执行任何磁盘 I/O 操作,创建RDB文件结束之前,客户端发送的 BGSAVE 和 SAVE 命令会被服务器拒绝
2. 通过配置自动生成可以设置服务器配置的save选项,让服务器每隔一段时间自动执行一次BGSAVE命令,可以通过save选项设置多个保存条件,但只要其中任意一个条件被满足就会执行BGSAVE命令
例如:
save 900 1
save 300 10
save 60 10000
那么只要满足以下三个条件中的其中一个,BGSAVE命令就会被执行
- 服务器在 900 秒之内,对数据库进行了 1 次修改
- 服务器在 300 秒之内,对数据库进行了 10 次修改
- 服务器在 60 秒之内,对数据库进行了 10000 次修改
RDB的持久化配置
# 时间策略
save 900 1
save 300 10
save 60 10000
# 文件名称
dbfilename dump.rdb
# 文件保存路径
dir /home/work/app/redis/data/
# 如果持久化出错,主进程是否停止写入
stop-writes-on-bgsave-error yes
# 是否压缩
rdbcompression yes
# 导入时是否检查
rdbchecksum yes
配置其实非常简单,这里说一下持久化的时间策略具体是什么意思。
-
save 900 1 表示900s内如果有1条是写入命令,就触发产生一次快照,可以理解为就进行一次备份
-
save 300 10 表示300s内有10条写入,就产生快照
-
stop-writes-on-bgsave-error yes
这个配置也是非常重要的一项配置,这是当备份进程出错时,主进程就停止接受新的写入操作,是为了保护持久化的数据一致性问题
。如果自己的业务有完善的监控系统,可以禁止此项配置, 否则请开启。 -
压缩的配置
rdbcompression yes
,建议没有必要开启,毕竟Redis本身就属于CPU密集型服务器,再开启压缩会带来更多的CPU消耗,相比硬盘成本,CPU更值钱。 -
当然如果你想要
禁用RDB配置
,也是非常容易的,只需要在save的最后一行写上:save “”
RDB的优点
- RDB是一个非常紧凑的文件,它保存了某个时间点的数据集,
非常适用于数据集的备份
,比如你可以在每个小时保存一下过去24小时内的数据,同时每天保存过去30天的数据,这样即使出了问题你也可以根据需求恢复到不同版本的数据集. - RDB是一个紧凑的单一文件,很方便传送到另一个远端数据中心或者亚马逊的S3(可能加密),
非常适用于灾难恢复
. - RDB在保存RDB文件时父进程唯一需要做的就是fork出一个子进程,接下来的工作全部由子进程来做,父进程不需要再做其他IO操作,所以
RDB持久化方式可以最大化redis的性能.
- 与AOF相比,
在恢复大的数据集的时候,RDB方式会更快一些
.
RDB的缺点
- 如果你希望在redis意外停止工作(例如电源中断)的情况下丢失的数据最少的话,那么RDB不适合你.虽然你可以配置不同的save时间点(例如每隔5分钟并且对数据集有100个写的操作),
使Redis要完整的保存整个数据集是一个比较繁重的工作,你通常会每隔5分钟或者更久做一次完整的保存,万一在Redis意外宕机,你可能会丢失几分钟的数据.
- RDB 需要经常fork子进程来保存数据集到硬盘上,
当数据集比较大的时候,fork的过程是非常耗时的,可能会导致Redis在一些毫秒级内不能响应客户端的请求
.如果数据集巨大并且CPU性能不是很好的情况下,这种情况会持续1秒,AOF也需要fork,但是你可以调节重写日志文件的频率来提高数据集的耐久度.
AOF持久化
Append-only file,将“操作 + 数据”以格式化指令的方式追加到操作日志文件的尾部,在append操作返回后(已经写入到文件或者即将写入),才进行实际的数据变更,“日志文件”保存了历史所有的操作过程;当server需要数据恢复时,可以直接replay此日志文件,即可还原所有的操作过程。AOF相对可靠,它和mysql中bin.log、apache.log、zookeeper中txn-log简直异曲同工。AOF文件内容是字符串,非常容易阅读和解析。
AOF的整个流程大体来看可以分为两步
- 一步是命令的实时写入(如果是 appendfsync everysec 配置,会有1s损耗)
- 第二步是对aof文件的重写。
对于增量追加到文件这一步主要的流程是:命令写入=》追加到aof_buf =》同步到aof磁盘。
那么这里为什么要先写入buf在同步到磁盘呢?如果实时写入磁盘会带来非常高的磁盘IO,影响整体性能。
aof重写是为了减少aof文件的大小
,可以手动或者自动触发,关于自动触发的规则请看上面配置部分。fork的操作也是发生在重写这一步,也是这里会对主进程产生阻塞。
AOF生成方式
通过保存Redis服务器所执行的写命令来记录数据库状态的AOF文件刷新方式
appendfsync everysec
它其实有三种模式:
- always:每提交一个修改命令都调用fsync到AOF文件,非常慢,但是很安全;
- everysec:每秒都调用fsyns刷新到AOF文件,很快但可能丢失一秒内的数据;
- no:依靠OS进行刷新,redis不主动刷新AOF,这样最快但是安全性差;
一般情况下都采用 everysec 配置,这样可以兼顾速度与安全,最多损失1s的数据。
AOF的持久化配置
# 是否开启aof
appendonly yes
# 文件名称
appendfilename "appendonly.aof"
# 同步方式
appendfsync everysec
# aof重写期间是否同步
no-appendfsync-on-rewrite no
# 重写触发配置
auto-aof-rewrite-percentage 100
auto-aof-rewrite-min-size 64mb
# 加载aof时如果有错如何处理
aof-load-truncated yes
# 文件重写策略
aof-rewrite-incremental-fsync yes
aof-load-truncated yes
如果该配置启用,在加载时发现aof尾部不正确时,会向客户端写入一个log,但是会继续执行,如果设置为 no ,发现错误就会停止,必须修复后才能重新加载。
AOF的 优点
使用AOF 会让你的Redis更加耐久
: 你可以使用不同的fsync策略:无fsync,每秒fsync,每次写的时候fsync.使用默认的每秒fsync策略,Redis的性能依然很好(fsync是由后台线程进行处理的,主线程会尽力处理客户端请求),一旦出现故障,你最多丢失1秒的数据.AOF文件是一个只进行追加的日志文
件,所以不需要写入seek,即使由于某些原因(磁盘空间已满,写的过程中宕机等等)未执行完整的写入命令,你也可使用redis-check-aof工具修复
这些问题.- Redis 可以
在 AOF 文件体积变得过大时,自动地在后台对 AOF 进行重写
: 重写后的新 AOF 文件包含了恢复当前数据集所需的最小命令集合。 整个重写操作是绝对安全的,因为 Redis 在创建新 AOF 文件的过程中,会继续将命令追加到现有的 AOF 文件里面,即使重写过程中发生停机,现有的 AOF 文件也不会丢失。 而一旦新 AOF 文件创建完毕,Redis 就会从旧 AOF 文件切换到新 AOF 文件,并开始对新 AOF 文件进行追加操作。 AOF 文件有序地保存了对数据库执行的所有写入操
作, 这些写入操作以 Redis 协议的格式保存, 因此 AOF 文件的内容非常容易被人读懂, 对文件进行分析(parse)也很轻松。 导出(export) AOF 文件也非常简单: 举个例子, 如果你不小心执行了 FLUSHALL 命令, 但只要 AOF 文件未被重写, 那么只要停止服务器, 移除 AOF 文件末尾的 FLUSHALL 命令, 并重启 Redis , 就可以将数据集恢复到 FLUSHALL 执行之前的状态。
AOF的 缺点
- 对于相同的数据集来说,
AOF 文件的体积通常要大于 RDB 文件的体积
。 - 根据所使用的 fsync 策略,
AOF 的速度可能会慢于 RDB
。 在一般情况下, 每秒 fsync 的性能依然非常高, 而关闭 fsync 可以让 AOF 的速度和 RDB 一样快, 即使在高负荷之下也是如此。 不过在处理巨大的写入载入时,RDB 可以提供更有保证的最大延迟时间(latency)。
RDB VS AOF
Redis DataBase(简称RDB)
- 执行机制:快照,直接将databases中的key-value的二进制形式存储在了rdb文件中
- 优点:性能较高(因为是快照,且执行频率比aof低,而且rdb文件中直接存储的是key-values的二进制形式,对于恢复数据也快)
使用单独子进程来进行持久化,主进程不会进行任何IO操作,保证了redis的高性能 - 缺点:在save配置条件之间若发生宕机,此间的数据会丢失
RDB是间隔一段时间进行持久化,如果持久化之间redis发生故障,会发生数据丢失。所以这种方式更适合数据要求不严谨的时候
Append-only file (简称AOF)
- 执行机制:将对数据的每一条修改命令追加到aof文件
- 优点:数据不容易丢失
可以保持更高的数据完整性,如果设置追加file的时间是1s,如果redis发生故障,最多会丢失1s的数据;且如果日志写入不完整支持redis-check-aof来进行日志修复;AOF文件没被rewrite之前(文件过大时会对命令进行合并重写),可以删除其中的某些命令(比如误操作的flushall) - 缺点:性能较低(每一条修改操作都要追加到aof文件,执行频率较RDB要高,而且aof文件中存储的是命令,对于恢复数据来讲需要逐行执行命令,所以恢复慢)
AOF文件比RDB文件大,且恢复速度慢。