目录
- 概述
- RDB
- 持久化流程
- 指定备份文件的名称
- 指定备份文件存放的目录
- 触发RDB备份
- redis.conf 其他一些配置
- rdb的备份和恢复
- 优缺点
- 停止RDB
- AOF
- 持久化流程
- AOF启动/修复/恢复
- AOF同步频率设置
- rewrite压缩
- 原理
- 触发机制
- 重写流程
- no-appendfsync-on-rewrite
- 优缺点
- 如何选择
概述
Redis是一个基于内存的数据库,它的数据是存放在内存中,内存有个问题就是关闭服务或者断电会丢失。
Redis的数据也支持写到硬盘中,这个过程就叫做持久化。
Redis提供了2种不同形式的持久化方式。
- RDB(Redis DataBase)
- AOP(Append Of File)
RDB
RDB是在指定的时间间隔内将内存中的数据集快照写入磁盘,也就是行话讲的Snapshot快照,它恢复时是键快照文件直接读到内存里。
Redis会单独创建(fork)一个子进程进行持久化,会先将数据写入到一个临时文件中,待持久化过程都结束后,再用这个临时文件替换上次持久化好的文件。整个过程中,主进程是不进行任何IO操作的,这就是确保了极高的性能,如果需要进行大规模的恢复,且对数据恢复的完整性不是非常敏感,那RDB方式要比AOF方式更加的高效。RDB的缺点是最后一次持久化后的数据可能丢失。
持久化流程
Fork的作用是复制一个与当前进程一样的进程,新进程的所有数据(变量、环境变量、程序计数器等)数值都和原进程一致,它是一个全新的进程,并作为原进程的子进程。
在Linux程序中,fork()会产生一个和父进程完全相同的子进程,但子进程在此后多会exec系统调用,处于效率考虑,linux中引入了“写时复制技术”。
一般情况父进程和子进程会共用一段物理内存,只有进程空间的各段的内容要发生变化时,才会将父进程的内容复制一份给子进程。
指定备份文件的名称
在redis.conf中,可以修改rdb备份文件的名称,默认为dump.rdb,如下:
指定备份文件存放的目录
在redis.conf中,rdb文件的保存的目录是可以修改的,默认为Redis启动命令所在的目录,如下
触发RDB备份
方式1:自动备份,需配置备份规则
可在redis.conf中配置自动备份的规则,默认规则如下:
save用来配置备份的规则
save的格式: save 秒钟 写操作次数
默认是1分钟内修改了1万次,或5分钟内需修改了10次,或30分钟内修改了1次。
示例:设置20秒内有最少有3次key发生变化,则进行备份
save 20 3
方式2:手动执行命令备份(save | bgsave)
有2个命令可以触发备份。
**save:**save时只管保存,其他不管,全部阻塞,手动保存,不建议使用。
**bgsave:**redis会在后台异步进行快照操作,快照同时还可以响应客户端情况。
可以通过 lastsave 命令获取最后一次成功生成快照的时间。
方式3:flushall命令
执行flushall命令,也会产生dump.rdb文件,但里面是空的,无意义。
redis.conf 其他一些配置
1. stop-writes-on-bgsave-error
当磁盘满时,是否关闭redis的写操作。当redis无法写入磁盘的话,是否直接关掉redis的写操作,推荐yes。
rdbcompression
rdb备份是否开启压缩。对于存储到磁盘中的rdb快照文件,可以设置是否进行压缩,如果是的话,redis会采用LZF算法进行压缩。如果你不想小号CPU来进行压缩的话,可以设置为关闭此功能,推荐yes。
rdbchecksum
是否检查rdb备份文件的完整性。存储快照后,还可以让redis使用CRC64算法来进行数据校验,但是这样做会增加大约10%的性能消耗,如果希望获取最大的性能提升,可以关闭此功能。推荐yes。
rdb的备份和恢复
-
先通过config get dir 查询rdb文件的目录
-
然后将rdb的备份文件 *.rdb 文件拷贝到别的地方
cp dump.rdb dump2.rdb
- rdb的恢复
- 关闭redis
- 先把备份的文件拷贝到工作目录 cp dump2.rdb dump.rdb
- 启动redis,备份数据直接加载,数据被恢复
优缺点
优势
- 适合大规模数据恢复
- 对数据完整性和一致性要求不高更适合使用
- 节省磁盘空间
- 恢复速度快
缺点
- Fork的时候,内存中的数据会被克隆一份,大致2倍的膨胀,需要考虑
- 虽然Redis在fork的时候使用了写时拷贝技术,但是如果数据庞大时还是比较消耗性能
- 在备份周期在一定间隔时间做一次备份,所以如果Redis意外down的话,就会丢失最后一次快照后所有修改
停止RDB
动态停止RDB: redis-cli config set save ""
#save后给空值,表示禁用保存策略
AOF
以日志的形式来记录每个写操作(增量保存),将redis执行过的所有写指令记录下来(读操作不记录),只允追加文件但不可改写文件,redis启动之初会读取该文件重新构造数据,换言之,redis重启的话就根据日志文件的内容将写指令从前到后执行一次以完成数据的恢复工作。
AOF默认不开启,可以在 redis.conf 文件中对AOF进行配置:
appendonly no # 是否开启AOF,yes:开启,no:不开启,默认为no
appendfilename "appendonly.aof" # aof文件名称,默认为appendonly.aof
dir ./ # aof文件所在目录,默认./,表示执行启动命令时所在的目录,比如我们在/opt目录中,去执行redis-server /etc/redis.conf 来启动redis,那么dir此时就是/opt目录
AOF和RDB同时开启,系统默认取AOF的数据(数据不会存在丢失)
持久化流程
- 客户端的请求写命令会被append追加到AOF缓冲区内
- AOF缓冲区会根据AOF持久化策略[always,everysec,no]将操作sync同步到磁盘的AOF文件中
- AOF文件大小超过重写策略或手动重写时,会对AOF文件进行重写(rewrite),压缩AOF文件容量
- redis服务器重启时,会重新load加载AOF文件中的写操作达到数据恢复的目的
AOF启动/修复/恢复
AOF的备份机制和性能虽然和RDB不同,但是备份和恢复的操作同RDB一样,都是拷贝备份文件,需要恢复时再拷贝到Redis工作目录下,启动系统即加载。
正常恢复
- 修改默认的appendonly no,改为yes
- 将有数据的aof文件复制一份保存到对应的目录(查看目录:config get dir)
- 恢复:重启redis然后重新加载
异常恢复
- 修改默认的appendonly no,改为yes
- 如遇到aof文件损坏,通过 /usr/local/bin/redis-check-aof --fix appendonly.aof 进行恢复
AOF同步频率设置
可以在redis.config中配置AOF同步的频率。
有以下几种:
appendfsync always:每次写入立即同步,始终同步,每次redis的写入都会立刻记入日志;性能较差但数据完整性比较好。
appendfsync everysec:每秒同步,每秒同步,每秒记录日志一次,如果宕机,本秒数据可能丢失;更新的命令会放在内存中AOF缓冲区,每秒将缓冲区的命令追加到AOF文件。
appendfsync no:不主动同步,redis不主动进行同步,把同步交给操作系统。
rewrite压缩
原理
AOF采用文件追加方式,文件会越来越大,为了避免出现此情况,新增了重写机制,当AOF文件的大小超过锁审定的阈值时,Redis就会启动AOF文件的内容压缩,只保留可以恢复数据的最小指令集,可以使用命令bgrewriteaof触发重写。
AOF文件持续增长而过大时,会fork出一条新进程来将文件重写(也是先写临时文件,最后在rename替换旧文件),redis4.0版本后的重写,是指就把rdb的快照,以二进制的形式附在新的aof头部,作为已有的历史数据,替换掉原来的流水账操作。
触发机制
bgrewriteaof:
手动触发重写。
从 Redis 2.4 开始, AOF 重写由 Redis 自行触发, bgrewriteaof 仅仅用于手动触发重写操作。
redis会记录上次重写的aof大小,默认配置是当aof文件大小是上次rewrite后大小的2倍且文件大于64M时触发。
重写虽然可以节约大量磁盘空间,减少恢复时间,但是每次重写还是有一定负担的,因此设置redis满足一定条件才会进行重新。
auto-aof-rewrite-percentage:
设置重写基准值。
设置重写的基准值,默认100,当文件达到100%时开始重写(文件是原来重写后文件的2倍时重写)。
auto-aof-rewrite-min-size:
设置重写基准值。
设置重写的基准值,默认64MB,AOF文件大小超过这个值开始重写。
重写流程
127.0.0.1:6379> bgrewriteaof Background append only file rewriting started
- 手动执行 bgrewriteaof 命令触发重写,判断是否当前有bgfsave或bgrewriteaof在运行,如果有,则等待该命令结束后再继续执行
- 主进程fork出子进程执行重写操作,保证主进程不会阻塞
- 子进程遍历redis内存中的数据到临时文件,客户端的写请求同时写入aof_buf缓冲区和aof_rewrite_buf重写缓冲区保证原AOF文件完整性以及新AOF文件生成期间的新的数据修改动作不会丢失
- 子进程写完新的AOF文件后,向主进程发送信号,父进程更新统计信息
- 主进程把aof_rewrite_buf中的数据写入到新的AOF文件
- 使用新的AOF文件覆盖旧的AOF文件,完成AOF重写
no-appendfsync-on-rewrite
该参数表示在正在进行AOF重写时不会将AOF缓冲区中的数据同步到旧的AOF文件磁盘,也就是说在进行AOF重写的时候,如果此时有写操作进俩,此时写操作的命令会放在aof_buf缓存中(内存中),而不会将其追加到旧的AOF文件中,这么做是为了避免同时写旧的AOF文件和新的AOF文件对磁盘产生的压力。
默认是ON,表示关闭,即在AOF重写时,会对AOF缓冲区中的数据做同步磁盘操作,这在很大程度上保证了数据的安全性。
但在数据量很大的场景,因为两者都会消耗磁盘IO,对磁盘的影响较大,可以将其设置为“yes”减轻磁盘压力,但在极端情况下可能丢失整个AOF重写期间的数据。
如果no-appendfsync-on-rewrite为yes,不写入aof文件,只写入缓存,用户请求不会阻塞,但是在这段时间如果宕机会丢失这段时间的缓存数据。(降低数据安全性,提高性能)
如果no-appendfsync-on-rewrite为no,还是会把数据库往磁盘里刷,但是遇到重写操作,可能会发生阻塞。(数据安全,但是性能降低)。
优缺点
优点
- 备份机制更稳健,丢失数据概率更低
- 可读的日志文本,通过操作AOF文件,可以处理误操作
缺点
- 比RDB占用更多的磁盘空间
- 恢复备份速度要慢
- 每次读写都同步的话,有一定的性能压力
- 存在个别bug,造成不能恢复
如何选择
官方推荐2个都启用。
如果对数据不敏感,可以单独用RDB。
不建议单独使用AOF,因为可能会出现BUG。
如果只是做纯内存缓存,可以都不用。
官网建议
RDB持久化方式能够在指定的时间间隔对你的数据进行快照存储;
AOF持久化方式记录每次对服务器写的操作,当服务器重启的时候会重新执行这些命令来恢复原始数据,AOF命令以redis协议追加保存每次写的操作到AOF文件末尾。Redis还能对AOF文件进行后台重写,使得AOF文件的体积不至于过大。
如果只做缓存,你也可以不使用任何持久化方式。
其他情况建议同时开启两种持久化方式。在这种情况下,当redis重启的时候会优先载入AOF文件来恢复原始的数据,因为在通常情况下AOF文件保存的数据集要比RDB文件保存的数据集要完整。RDB更适合用于备份数据库,快速重启,而且不会有AOF可能潜在的bug,留着作为一个万一的手段。
性能建议:
因为RDB文件只用作后备用途,建议只在Slave上持久化RDB文件,而且只要15分钟备份一次就够了,只保留 save 900 1 这一条;
如果使用AOF,好处是在最恶劣的情况下也只会丢失不超过两秒数据,启动脚本较简单只load自己的AOF文件就可以了;
AOF的代价,一是带来持续的IO,二是AOF rewrite的最后将rewrite过程中产生的新数据(aof_rewrite_buf)写到文件造成的阻塞几乎是不可避免的;
只要硬盘许可,应该尽量减少AOF rewrite的频率,AOF重写的基数大小默认值64M(autoaof-rewrite-min-size)太小了,可以设置到5G以上;
默认超过原大小100%(auto-aof-rewrite-percentage)大小时重写可以改到适当的数值。