redis笔记06-持久化rdb和aof

目录

【rdb】

【aof】

【Redis持久化的深入分析】


Redis持久化: 即把数据存储于硬盘中,即使断电后也不会丢失数据。Redis的持久化有2种方式:rdb快照持久化 和 aof日志。

◆rdb ,生成某一个时刻的快照,然后保存到二进制文件中
◆aof ,记录每一条写命令,追加到文件中,打开可以看到具体的操作记录
◆混合模式,它上面两种方式的结合

【rdb】

rdb的工作原理: 每隔N分钟或N次写操作后,从内存dump数据形成rdb文件并压缩,然后放在备份目录。优势在于:恢复速度很快。

手动触发:

◆save ,会让redis处于阻塞的状态,直到rdb持久化完成,线上环境要谨慎使用

◆bgsave ,它会fork出一个子进程(fork的过程会有短暂的阻塞),用来执行持久化,主进程继续响应客户端请求

自动触发:

◆ 执行命令最终执行的是bgsave,在m秒内,有n个key发生改变,就会触发

优点:
◆容灾性好,方便备份
◆性能最大化, fork出一个子进程来操作,对主进程没有影响
◆数据比较多时,相对于aof启动效率比较高
缺点:
◆可能会造成部分数据丢失

关于rdb的配置,打开 redis.conf 文件:

相关参数说明:

save 900 1  #900秒之后至少1个关键字发生变化。
save 300 10 #300秒之后至少10个关键字发生变化。
save 60 10000 #60秒之后至少10000个关键字发生变化。
(如果这3个选项都屏蔽,则rdb禁用)

stop-writes-on-bgsave-error yes #后台存储错误停止写(后台备份进程出错时,主进程停不停止写入)
rdbcompression yes #使用LZF压缩rdb文件。(导出的rdb文件是否压缩)
rdbchecksum yes #存储和加载rdb文件时校验。(导入rbd恢复时数据时,要不要检验rdb的完整性)
dbfilename dump.rdb #设置rdb文件名。(导出来的rdb文件名)
dir ./ #设置工作目录,rdb文件会写入该目录。(rdb的放置路径)

为了方便测试,将 save 60 10000 改为 save 60 3000.

此时测试写入:

使用批量写入工具可以方便测试:redis-benchmark

方法:./bin/redis-benchmark -n 10000 即可批量写入10000条数据

此时,可以看到出现了一个 dump.rdb 文件:

接着继续单个写入:

然后,假设此时断电了.... 再次重新开启服务后,会发现刚才写入的 set address 数据丢失了。原因在于,60秒需要写入3000条才会保存,而此时并没有3000条,所以并没有保存。这就是rdb的缺陷:在2个保存点之间断电,将会丢失1~N分钟的数据。

出于对持久化的更精细要求,redis增添了aof方式:append only file

【aof】

同步策略

everysec ,每秒同步一次
always ,每次操作后都要同步一次
no ,由操作系统调度进行同步

重写策略
◆手动触发,执行bgrewiteaof命令
◆自动触发

auto-aof-rewrite-percentage:当前AOF文件大小和最后一-次重写后的大小之间的比率等于或者等于指定的增长百分比,如100代表当前AOF文件是上次重写的两倍时候才重写
auto-aof-rewrite-min-size:当AOF文件大小大于该值时候才可能重写

优点
◆数据安全,不会造成数据的丢失
缺点
◆比rdb重启效率低;运行效率比rdb低

基本配置:打开 redis.conf ,搜索 aof:

将上面的appendonly no 改为 appendonly yes,并设置aof的保存目录。

具体配置如下:

appendonly no  #是否打开aof日志功能
appendfsync always #每1个命令,都立即同步到aof。安全,速度慢(系统不缓冲,直接写,慢,丢失数据少)
appendfsync everysec #折中方案,每秒写1次(折衷,每秒写1次)
appendfsync no #写入工作交给操作系统,由操作系统判断缓冲区大小,统一写入到aof. 同步频率低,速度快。(系统缓冲,统一写,速度快)
no-appendfsync-on-rewrite yes #正在导出rdb快照的过程中,要不要停止同步aof(重写aof时同步最新数据)
auto-aof-rewrite-percentage 100 #aof文件大小比起上次重写时的大小,增长率100%时,重写(当前aof文件是上次重写是大N%时重写)
auto-aof-rewrite-min-size 64mb #aof文件,至少超过64M时,重写(aof重写至少要达到的大小)

测试演示,假设 redis.conf 配置如下:

修改完成后保存退出,然后连接写入数据,理论上1秒钟就会有aof.

查看 appendonly.aof 文件:

假设刚写入一个数据,然后断电了,重启后再查看刚才写入的数据还是在的,说明用这个方法实现持久化还是很不错的。

但是有个问题,如下:

发现什么了吗?同一个key,使用incr 命令操作了N次,aof里面就会写入N次,这样会导致aof文件很大。

假如此时这个age已经增长到100,那么恢复时依然会从20,加1、加1... 一直增长到100。

有没有办法直接恢复为100呢?当时有的。方法如下:把最终的结果逆化为新的变量,可能是set,或者zset等等。此时相当于直接 set age 100。此过程叫做:aof重写

需要用到上面配置文件里的:

① auto-aof-rewrite-percentage 100 :假如上次aof的文件大小是2MB,那么下次打到4MB则重写,再下次8MB重写,再下次16MB...

② auto-aof-rewrite-min-size 64mb:因为前期文件较小,重写的意义不大,所以使用后面的设置,当大于64MB的时候再重写。

其实还有一个命令:bgrewriteaof 可以直接马上重写。

之前没有用到aof的时候,1秒钟可以写入1800条,但是打开aof并设置为1秒钟备份一次,测试结果1秒钟可以写入1300条,性能稍微会下降。

思考一个问题,恢复数据时rdb和aof哪个更快?答案是 rdb快, 因为rdb是数据的内存映射直接载入到内存,而aof是命令需要逐条执行。

【Redis持久化的深入分析】

AOF 里记录的是 Redis 收到的每一条命令,这些命令是以文本形式保存的。 AOF 还有一个好处:它是在命令执行后才记录日志,所以不会阻塞当前的写操作。不过,AOF 也有两个潜在的风险。

  • 如果刚执行完一个命令,还没有来得及记日志就宕机了,那么这个命令和相应的数 据就有丢失的风险。

  • AOF 虽然避免了对当前命令的阻塞,但可能会给下一个操作带来阻塞风险。这是因为,AOF 日志也是在主线程中执行的,如果在把日志文件写入磁盘时,磁盘写压力大,就 会导致写盘很慢,进而导致后续的操作也无法执行了。

如果不小心运行了flushall, 立即 shutdown nosave 关闭服务器,然后手工编辑 aof 文件, 去掉文件中的 “flushall ”相关行, 然后开启服务器,就可以导入回原来数据。但是如果flushall之后,系统恰好bgrewriteaof了,那么aof就清空了,数据就丢失了,因此类似flush之类的操作一定要谨慎!

三种写回策略(AOF 配置项 appendfsync 的三个可选值):

  • Always,同步写回:每个写命令执行完,立马同步地将日志写回磁盘;

  • Everysec,每秒写回:每隔一秒把缓冲区中的内容写入磁盘;

  • No,操作系统控制的写回:由操作系统决定何时将缓冲区内容写回磁盘。

我们一定要小心 AOF 文件过大带来的性能问题 ————— AOF 重写机制。比如:set k v,然后set k v2,最终只AOF记录后者。
AOF 日志由主线程写回,但是重写过程是由后台线程 bgrewriteaof 来完成的,这也是为了避免阻塞主线程。

用 AOF 方法进行故障恢复的时候,需要逐一把操作日志都执行一遍。如果操作日志非常多,Redis 就会恢复得很缓慢,影响到正常使用。和 AOF 相比,RDB 记录的是某一时刻的数据,可以快速恢复。

Redis 的数据都在内存中,为了提供所有数据的可靠性保证,它执行的是全量快照,也就是说,把内存中的所有数据都记录到磁盘中,会花费很多时间。而且,全量数据越多,RDB 文件就越大,往磁盘上写数据的时间开销就越大。

Redis 提供了两个命令来生成 RDB 文件,分别是 save 和 bgsave。

  • save:在主线程中执行,会导致阻塞;

  • bgsave:创建一个子进程,专门用于写入 RDB 文件,避免了主线程的阻塞,这也是 Redis RDB 文件生成的默认配置。

快照时数据能修改吗? bgsave 子进程是由主线程 fork 生成的,可以共享主线程的所有内存数据。 bgsave 子进程运行后,开始读取主线程的内存数据,并把它们写入 RDB 文件。Redis 会使用 bgsave 对当前内存中的所有数据做快照,这个操作是子进程在后台完 成的,这就允许主线程同时可以修改数据。

我们可以做增量快照:做了一次全量快照后,后续的快照只对修改的数据进行快照记录,这样可以避免每次全量快照的开销。

快照的频率不好把握,如果频率太低,两次快照间一旦宕机,就可能有比较多的数据丢失。如果频率太高, 又会产生额外开销,那么,还有什么方法既能利用 RDB 的快速恢复,又能以较小的开销做 到尽量少丢数据呢? Redis 4.0 中提出了一个混合使用 AOF 日志和内存快照的方法。简单来说,内存快照以一定的频率执行,在两次快照之间,使用 AOF 日志记录这期间的所有命令操作。

关于持久化的总结:

  • 数据不能丢失时,内存快照和 AOF 的混合使用是一个很好的选择; 

  • 如果允许分钟级别的数据丢失,可以只使用 RDB;

  • 如果只用 AOF,优先使用 everysec 的配置选项,因为它在可靠性和性能之间取了一个 平衡。

参考资料:https://time.geekbang.org/column/intro/100056701

  • 2
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 2
    评论
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

浮尘笔记

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值