Redis持久化相关
关于Redis持久化
- RDB(redis database):在指定的时间间隔对数据进行快照存储,全量存储。它以紧缩的二进制文件保存Redis数据库某一时刻所有数据对象的内存快照,可用于Redis的数据备份、转移与恢复。
- AOF(append only file):记录每次对服务器写的操作,当服务器重启的时候会重新执行这些命令来恢复原始的数据,增量存储。
RDB
save 900 1
每15分钟检查一次,有1(至少)个key变动就保存
save 300 10
每5分钟检查一次,有10(至少)个key变动就保存
save 60 10000
每1分钟检查一次,有10000(至少)个key变动就保存
# 时间策略
save 900 1
save 300 10
save 60 10000
# 文件名称
dbfilename dump.rdb
# 文件保存路径
dir /data
# 如果持久化出错,主进程是否停止写入
stop-writes-on-bgsave-error yes
# 是否压缩
rdbcompression yes
# 导入时是否检查
rdbchecksum yes
如果想要禁用RDB配置,也是非常容易的,只需要在save的最后一行写上:save ""
手动触发与Redis定时触发
手动触发
- save:会阻塞当前Redis服务器,直到持久化完成,线上应该禁止使用。
- bgsave:该触发方式会fork一个子进程,由子进程负责持久化过程,因此阻塞只会发生在fork子进程的时候。
自动触发
- 根据我们的 save m n 配置规则自动触发;
- 从节点全量复制时,主节点发送rdb文件给从节点完成复制操作,主节点会触发 bgsave;
- 执行 debug reload 时;
- 执行 shutdown时,如果没有开启aof,也会触发。
这里注意的是 fork 操作会阻塞,导致Redis读写性能下降。我们可以控制单个Redis实例的最大内存,来尽可能降低Redis在fork时的事件消耗。以及上面提到的自动触发的频率减少fork次数,或者使用手动触发,根据自己的机制来完成持久化。
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
appendfsync everysec 它其实有三种模式:
- always:把每个写命令都立即同步到aof,很慢,但是很安全
- everysec:每秒同步一次,是折中方案,默认值
- no:redis不处理交给OS来处理,非常快,但是也最不安全
AOF的整个流程大体来看可以分为两步,
- 一步是命令的实时写入(如果是 appendfsync everysec 配置,会有1s损耗),
- 命令写入
- 追加到aof_buf
- 同步到aof磁盘
- 第二步是对aof文件的重写。aof重写是为了减少aof文件的大小。
手动触发重写
bgrewriteaof 命令
自动触发重写
根据配置规则来触发(文件达到一定的大小时)
- 在重写期间,由于主进程依然在响应命令,为了保证最终备份的完整性;因此它依然会写入旧的AOF file中,如果重写失败,能够保证数据不丢失。
- 为了把重写期间响应的写入信息也写入到新的文件中,因此也会为子进程保留一个buf,防止新写的file丢失数据。
- 重写是直接把当前内存的数据生成对应命令,并不需要读取老的AOF文件进行分析、命令合并。
- AOF文件直接采用文本协议,主要是兼容性好、追加方便、可读性高、可人为修改修复。
AOF的文件内容
set name "lisi"
lpush names "lisi"
这几个命令生成的AOF文件内容为
*2
$6
SELECT
$1
0
*3
$3
set
$4
name
$4
lisi
*3
$5
lpush
$5
names
$4
lisi
AOF 混合持久化
Redis 4.0版本后AOF支持了混合持久化,文件前半部分为RDB格式,后半部分为AOF格式。
Multi Part AOF
Redis 7.0版本又引入了Multi Part AOF。
顾名思义,MP-AOF就是将原来的单个AOF文件拆分成多个AOF文件。在MP-AOF中,我们将AOF分为三种类型,分别为:
- BASE:表示基础AOF,它一般由子进程通过重写产生,该文件最多只有一个。
- INCR:表示增量AOF,它一般会在AOFRW开始执行时被创建,该文件可能存在多个。
- HISTORY:表示历史AOF,它由BASE和INCR AOF变化而来,每次AOFRW成功完成时,本次AOFRW之前对应的BASE和INCR AOF都将变为HISTORY,HISTORY类型的AOF会被Redis自动删除。
为了管理这些AOF文件,我们引入了一个manifest(清单)文件来跟踪、管理这些AOF。同时,为了便于AOF备份和拷贝,我们将所有的AOF文件和manifest文件放入一个单独的文件目录中,目录名由appenddirname配置(Redis 7.0新增配置项)决定。
MP-AOF的引入也为Redis的数据持久化带来了更多的想象空间。比如在开启aof-use-rdb-preamble时,BASE AOF本质是一个RDB文件,因此我们在进行全量备份的时候无需在单独执行一次BGSAVE操作。直接备份BASE AOF即可。MP-AOF支持关闭自动清理HISTORY AOF的能力,因此那些历史的AOF有机会得以保留,并且目前Redis已经支持在AOF中加入timestamp annotation,因此基于这些我们甚至可以实现一个简单的PITR能力( point-in-time recovery)。
从持久化中恢复数据
RDB vs AOF
RDB优点
- RDB是一个紧凑压缩的二进制文件,代表Redis在某一个时间点上的数据快照,非常适合用于备份、全量复制等场景。
- RDB对灾难恢复、数据迁移非常友好,RDB文件可以转移至任何需要的地方并重新加载。
- RDB是Redis数据的内存快照,数据恢复速度较快,相比于AOF的命令重放有着更高的性能。
RDB缺点
- RDB方式无法做到实时或秒级持久化。因为持久化过程是通过fork子进程后由子进程完成的,子进程的内存只是在fork操作那一时刻父进程的数据快照,而fork操作后父进程持续对外服务,内部数据时刻变更,子进程的数据不再更新,两者始终存在差异,所以无法做到实时性。
- RDB持久化过程中的fork操作,会导致内存占用加倍,而且父进程数据越多,fork过程越长。
- Redis请求高并发可能会频繁命中save规则,导致fork操作及持久化备份的频率不可控;
- RDB文件有文件格式要求,不同版本的Redis会对文件格式进行调整,存在老版本无法兼容新版本的问题。
AOF优点
- AOF持久化有更好的实时性,我们可以选择三种不同的方式(appendfsync):no、every second、always,every second作为默认的策略具有最好的性能,极端情况下可能会丢失一秒的数据。
- AOF文件只有append操作,无复杂的seek等文件操作,没有损坏风险。即使最后写入数据被截断,也很容易使用redis-check-aof工具修复;
- 当AOF文件变大时,Redis可在后台自动重写。重写过程中旧文件会持续写入,重写完成后新文件将变得更小,并且重写过程中的增量命令也会append到新文件。
- AOF文件以已于理解与解析的方式包含了对Redis中数据的所有操作命令。即使不小心错误的清除了所有数据,只要没有对AOF文件重写,我们就可以通过移除最后一条命令找回所有数据。
- AOF已经支持混合持久化,文件大小可以有效控制,并提高了数据加载时的效率。
AOF缺点
- 对于相同的数据集合,AOF文件通常会比RDB文件大;
在特定的fsync策略下,AOF会比RDB略慢。一般来讲,fsync_every_second的性能仍然很高,fsync_no的性能与RDB相当。但是在巨大的写压力下,RDB更能提供最大的低延时保障。 - 在AOF上,Redis曾经遇到一些几乎不可能在RDB上遇到的罕见bug。一些特殊的指令(如BRPOPLPUSH)导致重新加载的数据与持久化之前不一致,Redis官方曾经在相同的条件下进行测试,但是无法复现问题。
使用建议
如果仅仅是使用Redis作为缓存工具,所有数据可以根据持久化数据库进行重建,则可关闭持久化功能,做好预热、缓存穿透、击穿、雪崩之类的防护工作即可。
一般情况下,Redis会承担更多的工作,如分布式锁、排行榜、注册中心等,持久化功能在灾难恢复、数据迁移方面将发挥较大的作用。建议遵循几个原则:
- 不要把Redis作为数据库,所有数据尽可能可由应用服务自动重建。
- 使用4.0以上版本Redis,使用AOF+RDB混合持久化功能。
- 合理规划Redis最大占用内存,防止AOF重写或save过程中资源不足。
- 避免单机部署多实例。
- 生产环境多为集群化部署,可在slave开启持久化能力,让master更好的对外提供写服务。
- 备份文件应自动上传至异地机房或云存储,做好灾难备份。
参考
一文看懂Redis的持久化原理
Redis专题:万字长文详解持久化原理-内容更优
Redis 7.0 Multi Part AOF的设计和实现