Redis数据持久化
个人博客
redis深入学习之实现主从和哨兵
Redis深入学习之5种基本数据类型
前言
Redis 的数据全部在内存里,之所以需要持久化在硬盘是为了在之后能重用数据,或者是为了防止系统故障、宕机导致内存中的数据全部丢失。另外,存储在Redis中的数据有可能是经过长时间计算得出的,或者有程序正在使用Redis存储的数据进行计算,所以用户会希望自己可以将这些数据存储起来以便之后使用,不需要重新计算了。
Redis提供了两种不同的持久化方法来将数据存储到硬盘里面。一种方法叫快照(RDB),他可以将存在于某一时刻的数据都写入硬盘里面。另外一种方法叫做只追加文件(AOF),他会在执行写命令时,将被执行的命令写入硬盘里面。这两种持久化方法既可以同时使用,又可以单独使用,在某些情况下甚至两种方法都不使用,具体选择哪种持久化方法需要根据用户的数据以及应用来决定。
快照持久化
概念
Redis可以通过创建快照来获得存储在内存里面的数据在某个时间点上的副本。在创建快照之后,用户可以对快照进行备份,可以讲快照复制到其他服务器从而创建具有相同数据的服务器副本,还可以将快照留在原地以便重启服务器时使用。
创建快照(RDB)的方法
- 客户端可以通过向Redis发送BGSAVE命令来创建一个快照。对于支持BGSAVE命令的平台来说(基本所有的平台都只支持,除了windows平台),Redis会调用fork来创建一个子进程,然后子进程负责将快照写入磁盘,而父进程则继续处理命令请求。
- 客户端还可以通过向Redis发送SAVE命令来创建一个快照,接到SAVE命令的Redis服务器在快照创建完毕之前将不再响应任何其他命令。SAVE命令并不常用,我们通常只会在没有足够内存区执行BGSAVE命令的情况下,又或者即时等待持久化操作执行完毕也无所谓的情况下,才会使用这个命令。
- 如果用户设置了save配置选项,比如
save 60 10000
,那么从Redis最近一次创建快照之后开始算起,当“60秒之内有10000次写入”,这个条件被满足时,Redis就会自动触发BGSAVE命令。如果 用户设置了多个save配置选项,那么当任意一个save配置选项所设置的条件被满足时,Redis就会触发一次BGSAVE命令。 - 当Redis通过SHUTDOWN命令接收到关闭服务器的请求时,或者接收到标准TERM信号时,会执行一个SAVE命令,阻塞所有的客户端,不在执行客户端发送的任何命令,并在SAVE命令执行完毕之后关闭服务器。
- 当一个Redis服务器连接另一个Redis服务器,并向对象发送SYNC命令来开始一次复制操作的时候,如果主服务器目前没有在执行BGSAVE操作,或者主服务器并非刚刚执行完BGSAVE操作,那么主服务器就会执行BGSAVE命令。
RDB优缺点
- RDB会生成多个数据文件,每个数据文件都代表了某一个时刻中 redis 的数据,这种多个数据文件的方式,非常适合做冷备,可以将这种完整的数据文件发送到一些远程的安全存储上去,比如说 Amazon 的 S3 云服务上去,在国内可以是阿里云的 ODPS 分布式存储上,以预定好的备份策略来定期备份redis中的数据。
- RDB 对 redis 对外提供的读写服务,影响非常小,可以让 redis 保持高性能,因为 redis 主进程只需要 fork 一个子进程,让子进程执行磁盘 IO 操作来进行 RDB 持久化即可。
- 相对于 AOF 持久化机制来说,直接基于 RDB 数据文件来重启和恢复 redis 进程,更加快速。
- 如果想要在 redis 故障时,尽可能少的丢失数据,那么 RDB 没有 AOF 好。一般来说,RDB 数据快照文件,都是每隔 5 分钟,或者更长时间生成一次,这个时候就得接受一旦 redis 进程宕机,那么会丢失最近 5 分钟的数据。
- RDB 每次在 fork 子进程来执行 RDB 快照数据文件生成的时候,如果数据文件特别大,可能会导致对客户端提供的服务暂停数毫秒,或者甚至数秒。
AOF持久化
概念
简单的来说,AOF持久化会将被执行的写命令写到AOF文件的末尾,以此来记录数据发生的变化。因此,Redis只要从头到尾重新执行以此AOF文件包含的所有写命令,就可以恢复AOF文件所记录的数据集。
打开及配置AOF持久化
AOF持久化可以通过配置appendonly yes
配置选项来打开。然后可以通过配置appendfsync
配置选项对AOF文件的同步频率。
选项 | 同步频率 |
---|---|
alawys | 每个Redis写命令都要同步写入硬盘,这样做会严重降低Redis的速度 |
everysec | 每秒执行一次同步,显式的将多个写命令同步到硬盘 |
no | 让操作系统来决定应该何时进行同步 |
一般来说,比较常用的是appendfsync everysec
选项,让Redis以每秒一次的频率对AOF文件进行同步。Redis每秒同步一次AOF文件的性能和不使用任何持久化特性时的性能相差无几,而通过每秒同步一次AOF文件,Redis可以保证,即时出现系统崩溃,用户最多丢失一秒之内产生的数据。
AOF的优缺点
- AOF 可以更好的保护数据不丢失,一般 AOF 会每隔 1 秒,通过一个后台线程执行一次
fsync
操作,最多丢失 1 秒钟的数据。 - AOF 日志文件以
append-only
模式写入,所以没有任何磁盘寻址的开销,写入性能非常高,而且文件不容易破损,即使文件尾部破损,也很容易修复。 - AOF 日志文件即使过大的时候,出现后台重写操作,也不会影响客户端的读写。因为在
rewrite
log 的时候,会对其中的指导进行压缩,创建出一份需要恢复数据的最小日志出来。再创建新日志文件的时候,老的日志文件还是照常写入。当新的 merge 后的日志文件 ready 的时候,再交换新老日志文件即可。 - AOF 日志文件的命令通过非常可读的方式进行记录,这个特性非常适合做灾难性的误删除的紧急恢复。比如某人不小心用
flushall
命令清空了所有数据,只要这个时候后台rewrite
还没有发生,那么就可以立即拷贝 AOF 文件,将最后一条flushall
命令给删了,然后再将该AOF
文件放回去,就可以通过恢复机制,自动恢复所有数据。 - 对于同一份数据来说,AOF 日志文件通常比 RDB 数据快照文件更大。
- AOF 开启后,支持的写 QPS 会比 RDB 支持的写 QPS 低,因为 AOF 一般会配置成每秒
fsync
一次日志文件,当然,每秒一次fsync
,性能也还是很高的。(如果实时写入,那么 QPS 会大降,redis 性能会大大降低) - 以前 AOF 发生过 bug,就是通过 AOF 记录的日志,进行数据恢复的时候,没有恢复一模一样的数据出来。所以说,类似 AOF 这种较为复杂的基于命令日志/merge/回放的方式,比基于 RDB 每次持久化一份完整的数据快照文件的方式,更加脆弱一些,容易有 bug。不过 AOF 就是为了避免 rewrite 过程导致的 bug,因此每次 rewrite 并不是基于旧的指令日志进行 merge 的,而是基于当时内存中的数据进行指令的重新构建,这样健壮性会好很多。
RDB和AOF到底该如何选择
- 不要仅仅使用 RDB,因为那样会导致你丢失很多数据
- 也不要仅仅使用 AOF,因为那样有两个问题,第一,你通过 AOF 做冷备,没有 RDB 做冷备,来的恢复速度更快; 第二,RDB 每次简单粗暴生成数据快照,更加健壮,可以避免 AOF 这种复杂的备份和恢复机制的 bug。
- redis 支持同时开启开启两种持久化方式,我们可以综合使用 AOF 和 RDB 两种持久化机制,用 AOF 来保证数据不丢失,作为数据恢复的第一选择; 用 RDB 来做不同程度的冷备,在 AOF 文件都丢失或损坏不可用的时候,还可以使用 RDB 来进行快速的数据恢复。
补充Redis 4.0 混合持久化
重启 Redis 时,我们很少使用 rdb 来恢复内存状态,因为会丢失大量数据。我们通常使用 AOF 日志重放,但是重放 AOF 日志性能相对 rdb 来说要慢很多,这样在 Redis 实例很大的情况下,启动需要花费很长的时间。
Redis 4.0 为了解决这个问题,带来了一个新的持久化选项——混合持久化。将 rdb 文件的内容和增量的 AOF 日志文件存在一起。这里的 AOF 日志不再是全量的日志,而是自持久化开始到持久化结束的这段时间发生的增量 AOF 日志,通常这部分 AOF 日志很小。
于是在 Redis 重启的时候,可以先加载 rdb 的内容,然后再重放增量 AOF 日志就可以完全替代之前的 AOF 全量文件重放,重启效率因此大幅得到提升。
参考书籍《Redis 实战》