您的位置:首页 > 数据库 > Redis

一眼就能看懂的Redis持久化的RDB和AOF

2019-08-22 23:31 1216 查看
版权声明:本文为博主原创文章,遵循 CC 4.0 by-sa 版权协议,转载请附上原文出处链接和本声明。 本文链接:https://blog.csdn.net/valada/article/details/100026413

本篇 chat 主要将一下redis 持久化通过本 chat 你将了解到1、什么是redis持久化以及持久化的作用2、redis持久的方式3、RDB持久化的方式4、AOF持久化的方式5、二者优劣6、实际中选择

前言

前面将了 redis 的主从复制以及怎么搭建,还介绍了哨兵模式以及哨兵模式的搭建。虽然操作跟上了,但是还是补一下 redis 的持久化。redis 之所以这么流行,很大一部分原因便是持久化,断电重启数据不消失,使得redis在数据库领域中站稳了脚。前文将的主从复制其实就是依赖持久化的,如果没有持久化,这些数据都不会从主服务器备份到从服务器。下文我们就讲讲 redi s的持久化。

说起 redis 持久化,大家或多或少都知道一些,简单点一句话也能概括。redis 通过 RDB 和 AOF 方式将数据存入磁盘,实现持久化。RDB 是定期生成快照存入磁盘中,AOF 是将写操作存入磁盘中。二者各有优劣,RDB 是存放数据库中数据,适合做数据备份,但是数据可能不全,最近几分钟的数据可能没有。AOF 是每秒中执行一次,如果有写操作的命令就存储起来,最多只会丢失1秒钟的数据,适合做数据恢复。但是这个就不适合做数据备份了,并且由于每秒都会执行多多少少会抢占 redis 的内存,会影响性能。但是在实际应用中是二者是配合使用的。

下面就来具体的讲讲 RDB 和 AOF 吧

RDB

RDB 的全称是 redis database. 顾名思义,RDB 就是将 redis 数据库,用来存储数据的,所以通过 RDB 方式持久化就是将存在 redis 内存中的数据写入到 RDB 文件中保存到磁盘上从而实现持久化的。RDB 文件是一个压缩的二进制文件,通过这个文件可以还原 redis 数据库的数据,从而达到数据恢复的目的,借用一下《redis 设计与实现》讲的这张图,途中数据库状态可以理解为redis内存中存储的数据。 既然 RDB 持久化的方式是生成 RDB 文件,那么这个 RDB 文件是怎么生成的呢?RDB文件生成的方式有两种,一种是通过命令手动生成快照,还有一个是通过配置自动生成快照。下面我们来分别看看。

通过 save 和 bgsava 命令生成 RDB 文件

这两个命令都是可以直接运行的。

save 命令,会阻塞服务器进程,只有当 RDB 文件生成成功才会接着响应服务端的其他命令。 而 bgsave ,既然有这个命令,肯定是和save有所不同的,bgsave 不会阻塞服务器进程,会创建一个子进程来创建 RDB 文件 但是注意的是使用 bgsave 命令的时候,虽然是通过子进程生成 RDB 文件,不会阻塞服务进程,其他的命令可以执行,但是有几个命令是不能执行的。

save bgsavebgrewriteaof
在 bgsave 期间 服务器拒绝这三个命令,主要是方式线程间竞争产生问题。

通过配置文件自动生成 RDB

初了手动执行这两个命令外,还可以在配置文件中配合参数,达到条件的时候就会自动的生成RDB打开我们的配置文件redis.conf,找到如下图,这个是默认的配置。

save 900 1 表示在900秒内,如果发生了一次写操作,就触发bgsave命令生成RDB同理 save 300 10 在300秒内,发生了10次写操作,就触发bgsavesave 60 10000  在60秒内发生了10000次写操作,就触发bgsave
上面的这些可以进行配置,可以看到默认的设置,如果短时间内发生大量的写操作就会自动的触发 bgsave ,生成 RDB 文件, 防止数据丢失。

好了,上面虽然说达到这三个条件中的一个,redis 就会自动的生成 RDB 文件,那系统是怎样控制,又是怎样识别是否满足条件呢?原来啊,服务器维持了一个 dirty 计数器,以及一个 lastsave 属性。dirty 计数器记录着从上次 save/bgave 到现在发生了多少次写操作,没进行一次写操作,计数器就加1比如

set a  123计数器dirty 加1 set a 123 b 234 c 456计数器dirty 加3
而 lastsave 是 unix 时间戳,记录上次 save 或 bgsave 的时间。有了这两个属性,就可以判断什么时候执行啦,redis 服务器会周期性的执行 serverCron函数,默认的话是每100毫秒执行一次。这个 serverCron 函数先通过当前时间减去lastsave 获取时间间隔。如果 dirty 大于 saveparm.chranges并且时间间隔大于 saveparm.seconds那么就会触发 bgsave 生成 RDB 文件

其中 saveparm.seconds 和 saveparm.chranges 分别对应的是配置文件中设置的 save 900 1等。

既然生成了 RDB 文件,我们只知道 RDB 是一个压缩的二进制文件,那 RDB 文件到底结构是什么样的呢?我看了一下《redis 设计与实现》没有怎么看明白哈哈,感兴趣的可以去看看。

RDB 方式就讲到这里了,记住 RDB 方式,是定时的执行 bgsave 命令生成 RDB 文件保存在磁盘上实现持久化的。适合数据备份,用于数据恢复可能会丢失最近几分钟的数据。

AOF

全称是 append only file. AOF 持久化的方式是通过redis服务器记录保存下所有的写命令到AOF文件存放在磁盘上,实现持久化的,看下图: 怎样采用AOF的方式持久化呢?打开我们的配置文件,在配置文件中找到appendonly 改成yes 就可以采用AOF的方式备份了 我们启动 redis 服务,为了测试方便,我们新启的一个 redis 服务,数据库中没有任何key 我们看看 appendonly.aof 也是没有任何东西的。 现在我们存入一个 key 然后我们来看下 AOF 文件的内容: 可以看到,初了一些 $3 等一些特殊符号外我们可以看到我们执行的命令。

select 0set a bbb
但是我们一些读操作的就不会记录。由此可见,AOF 持久化就是将所有的写操作存入 AOF 文件中,当数据恢复的时候,执行 AOF 文件中的命令就可以获取数据了。

我们接着来看那,我向数据库中先加一个 key b ,然后删除 key a . 好了,现在我们再来看看 AOF 文件中是什么情况。 可以看到命令有:

select 0set a bbbset b ddddel a
所以 AOF 文件中包含了这四条命令,到这大家有没有发现一个问题,如果我重复的对某一个 key 值进行操作,那么 AOF 文件中就会记录所有的操作命令,但是实际上只有最后一次操作才是有效的,那这个 AOF 文件中是不是就有很多冗余的数据呢?

实际上是这样的,那怎么解决这个问题呢?这里就要提到一个命令啦

BGREWRITEAOF
和 RDB 中的 save 以及 bgsave 是类似的。不过 bgrewriteaof 命令的作 3ff7 用是重写 AOF 文件,为什么要重写呢,就是为了解决 AOF 文件中冗余的问题。我们先来手动执行一下这个命令 然后看看 AOF 文件中的内容 可以看到命令变成了
select 0set b ddd
重写之后,AOF 的文件里的命令就是有效的啦,但是我们总不能自己手动执行bgrewriteaof 命令吧,那我们在哪里配置呢?在 redis.conf 配置文件中有这两个参数。
auto-aof-rewrite-percentage 100
当 AOF 增长超过指定比例时,重写log file, 设置为0表示不自动重写Aof 日志,重写是为了使aof体积保持最小,而确保保存最完整的数据。
auto-aof-rewrite-min-size 64mb
触发aof rewrite的最小文件尺寸

也就是说在实际应用中,如果开启了 AOF 备份,可以设置这两个参数来重写AOF文件。

好了上面说了那么多,那 redis 服务怎么通过 AOF 文件来恢复数据的呢?其实很简单,就是将 AOF 文件中的命令一条一条的读取出来执行。看下图

最后再说一点嘿嘿。我们在配置文件中同时启用了 RDB 和 AOF ,那么服务启动的时候,会在用那个文件来回复数据呢?看下面这张图。 可以看到如果启动 AOF,就会采用 AOF 文件来回复数据,这是为什么呢,因为AOF 文件更新的频率更高,模式一秒中一次,所以用AOF 恢复的数据更加准确。

好了,只有这么多了哈哈,推荐大家看看《redis 设计与实现》也不建议大家从头往后看,调感兴趣的看吧,毕竟里面还是有很多原理对我们而言也不是一定非得弄懂的,大概了解一下就行,我比较懒哈哈。

阅读全文: http://gitbook.cn/gitchat/activity/5d5e83c192793378a9a70240

您还可以下载 CSDN 旗下精品原创内容社区 GitChat App ,阅读更多 GitChat 专享技术内容哦。

内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: