当前位置: 首页 > news >正文

谈谈redis的持久化

目录

1、redis的两个实现持久化的策略

2、RDB的触发时机

2.1 RDB的定期备份的实现方式

2.1.1 手动触发

        2.1.1.1 save

        2.1.1.2 bgsave

2.1.2 自动触发

2.2 RDB效果演示

还有几个补充的点:

3.AOF

3.1AOF实时写入文件的策略是否会影响redis的性能

3.2 AOF缓冲区的刷新机制

3.3 AOF的重写机制

3.4 AOF文件的保存也是两种触发方式:

4.还有两个问题

5. Redis的混合持久化


11000+字,耗时四个夜晚,只为你手里的赞赞和关注,求求了,你们的点赞和关注是我更新的最大动力!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!

说到redis的持久化,大家可能会想到mysql四个特性中的持久性,mysql的四个特性:原子性,一致性,持久性和隔离性,其实持久性就是持久化,说的就是要把数据存到硬盘中以此来实现数据的持久化存储;持久化的意思就是断电数据不会丢失,但是由于redis是一个内存型数据库,所有的的数据都是存在内存中,一但主机断电,内存中的数据就会丢失,所以如果要想实现redis的数据的持久化存储就得把数据存到硬盘中,但是redis相比较mysql之所以快,就是因为数据是存在内存中的,读取速度就会比硬盘快很多,现在如果是为了把实现redis的数据的持久化就把数据存到硬盘中,那redis和mysql还会有区别吗?不就是失去速度快的优势了吗?

既然redis为了存取速度快,就得把数据存到内存中,但是为了持久化数据,就把数据存到硬盘中,那Redis的数据到底该存在哪里呢?redis说我都不选,小孩在才做选择,我全都要,实际上呢?redis既会把数据存到内存中,方便快速读取和写入,也会把数据存到硬盘中,为的是持久化存储数据;

既然redis会把数据存到硬盘中,也会存到内存中,理论上这个两份数据应该是一致的。当然我说的是理论上,实际上同一个时刻,内存上的数据和硬盘上的数据是会有差别的。关键就在于当我们要去写入数据的时候,redis是如何把数据进行存储的?

当写入一个数据的时候,redis会同时往内存中写入一个数据,也会往硬盘中写入这个数据。那把数据存到硬盘中会导致redis的效率下降吗?毕竟往内存写入数据和往硬盘写入数据的速度是不一样的,实际上redis对于写入硬盘的数据有两个策略,以此保证了写入硬盘的数据并不会影响redis整体的速度。

1、redis的两个实现持久化的策略

        1.1 定时备份(RDB----Redis DataBase)

        1.2 实时备份(AOF----Append Only File)

举个例子来说明一下什么是定时备份,什么是实时备份?相信大家都会保存很多学习资料,学习到现在也肯定保存了很多学习资料,保存的实习资料肯定是存放在硬盘上,但是如果只是存了一份在硬盘上,如果硬盘一坏了,不就寄了,十多年的学习资料不就付之东流了吗?所以聪明的你不会保存到云盘上(因为云端会泄露数据,不是我说的),而是再另外找一个硬盘,我定时备份我的全部资料到这个硬盘中,比如,一个月更新一次,或者半个月更新一次,这就是定时保存,而redis的定时备份也是差不多这个,我们手动的去保存Redis的数据,具体的指令是save,bgsave。而实时保存呢?就是我一旦添加新的学习资料到我的硬盘中,我就会马上拷贝更新到我的另一个硬盘里。redis的实时备份也是如此。这是简单的说一下redis的定时备份和实时备份。

2、RDB的触发时机

RDB的过程实际就是给内存的数据生成一个“快照”,那什么是快照呢?快照其实就像警方在办案是给案发现场所拍照留下的任何资料,包括不限于照片,证物等等,为的是即使离开了案发现场,回到警局也能根据拍的照片,证物等等回原出现场所发生的一切,极大的方便了警方办案和分析现场所发生的一切,不用说天天在现场待着。所以RDB所谓的“快照”就是这样的,给内存生存一个快照,即使redis服务器关闭了,内存的数据也丢失了,就可以根据快照的内容也就是RDB文件存的数据,将原先内存的每一个数据完完整整的恢复到内存中,这样就实现了redis数据的持久化存储。

2.1 RDB的定期备份的实现方式
2.1.1 手动触发
        2.1.1.1 save

一但输入了这个指令,redis服务器就会全力以赴的去执行这个指令,其他的指令都会全部阻塞,一但生成快照的时间比较长,就会出现了类似于keys *指令的情况,所以要谨慎的使用这个指令,避免redis服务器照成卡顿,所以一般我们使用bgsave。为什么会是这样的呢?因为执行save的时候,会直接把内存中的数据直接一个一个写入到RDB文件中,而不是像bgsave一样:重新写入到一个临时的、空的RDB文件,然后将旧的RDB文件删掉,接着让这个临时的RDB文件成为新的RDB文件。

        2.1.1.2 bgsave

bg就是background,就是redis会在背后神不知鬼不觉的去生成一个快照,并且不会像save一样阻塞其他指令的执行,其他指令依旧可以在主进程继续执行。那大家可能就要问了,是不是redis额外使用了另一个线程去执行这个指令的,不是的,redis使用不是另外一个线程,而是重新创建一个新的进程去处理这个指令,使用了“并发编程”的方法。过程就如下图所示

  • 在redis执行bgsave之后,父进程也就是我们的redis服务器会去检查有没有其他进程正在执行bgsave指令,也就是有没有其他进程正在生成“快照”,因为有时候并不是只有一个客户端连接上redis服务器的,有可能有多个客户端就是也发了bgsave指令,所以当redis服务器识别到已经有别的进程正在执行bgsave,这次新的bgsave就不会继续执行下去,而是直接返回了;
  • 如果当前没有子进程正在执行bgsave,那么这次的bgsave指令就会生效,我们的父进程就去执行fork()方法,这个方法可能学过C++的同学比较清楚,学Java的可能不太清楚,我就是学Java,所以我也根据我了解到说一下,fork指令是Linux的一个指令,他会去创建一个和父进程完成一模一样的进程,子进程获得了一份与父进程完全相同的地址空间(代码段、数据段、堆、栈等)的副本,可以说子进程就是父进程的一个克隆体。说到这里,比较心细的同学就会说,既然是克隆体,那如果父进程内存中的数据非常大,比如有100GB(只是举个例子,夸张了一点),那不就得克隆很久,实际上并不会,而且这个克隆过程非常快,用到的技术叫做“写时拷贝”,说的是,子进程并不会在克隆的时候真正的去复制出来一份和父进程一样的数据并且保存下来,而是在逻辑上拥有一份与父进程完全相同的内存的数据的地址空间的副本,可以说是复制的是一份父进程内存中指向内存数据的页表,并非数据本身的内容。“写时拷贝”说的是只要当其中一个进程去修改他们共同指向的内存空间的数据时,才会在内存中真正地复制一份这个要被修改的内存数据,让另一个进程去指向这个新复制的内存数据。比如父子进程有一个共同指针是指向内存的数据 10,然后父进程想把10修改成20。那么这个时候就会在内存中新建一个数据10,让子进程指向这个数据10,而父进程指向的是修改后的20,这个时候他们指向的就不是同一个数据。这个就是“写时拷贝”。虽然在修改之后会触发复制,但是在子进程去生成RDB文件的过程中,时间并不会很长,所以也不会触发很多次的“写时拷贝”,所以对redis的整体效率的影响也不大。
  • 之后子进程就负责去继续生成RDB文件,而父进程就继续去接收来自各个客户端的指令,然后去执行指令。
  • 当子进程完成生成RDB文件之后,就会告诉父进程RDB文件已经生成完了;
  • 当父进程受到子进程完成生成RDB文件的信号时,父进程就会去更新一些统计信息,(具体统计信息是啥,留个悬念),子进程就销毁了。
2.1.2 自动触发

        自动触发生成新的RDB文件的时机是由在redis的配置文件中的两个参数决定的,可以设置多长时间并且要修改了几次,两个参数就是时间间隔(times)和修改次数(changes),满足条件之后就会去自动触发将redis内存的数据保存成一个新的RDB文件,并将旧的RDB文件删除,新的RDB文件就会去替换旧的RDB文件成为新的持久化保存的RDB文件,所以我们也可以知道只有一份唯一的RDB文件在硬盘中持久化保存。具体的RDB文件存储位置,以及自动触发的相关参数我们都可以从Redis的配置中查到。

redis的配置文件的位置 etc/redis/redis.conf

从redis的配置文件中我们看到redis的工作目录:/var/lib/redis

接下来我们看一下这个目录下面有啥,从下面这张图我们可以看到其实只有一个dump.rdb文件,这个文件就是redis的持久化文件,相同的我们既可以在redis的配置文件中查到并修改redis的工作目录,我们也可以改RDB文件的文件名,当然不改也无所谓,因为都是有默认值的。

RDB文件存的东西其实就是我们redis的内存数据,而且存的数据也是经过压缩的二进制数据,为什么要压缩,肯定就是为了节约空间。RDB文件的作用是什么呢?其实当redis服务器重新启用的时候,会去读取这个RDB文件中的数据到内存,我们之所以redis的增删改查比mysql快,也是因为Redis的数据就是存在内存中的,读取内存的数据肯定要把读取硬盘的速度要快很多啦。

接下来我们可以来看看这个RDB文件里面的数据是什么样子的呢?

其实我们可以到里面只有零星几个数据,仔细看还有一个key1,这是因为rdb文件存的就是二进制数据,我们看不懂也很正常,其实存的数据就是一个key1 ,一个key两个键值对。还有一个注意的点就是不要去修改这个rdb文件中的数据,因为redis重启的时候要去读取这里的数据,所以redis读取数据肯定有这个格式,一但我们修改了,导致redis重启的时候不能正常读取到rdb文件的数据到内存中,redis就无法正常启动了,这是一个非常严重的事情,非常严重,非常严重,所以一定不要手动修改里面的数据,我们看看就好。

话虽如此,难道只要我们不去修改这个RDB文件的数据,这个文件里面的数据就一定正常吗?就一定每次都可以被redis正确读取他的数据到内存中吗?当然不是,有可能这个rdb数据,会经过网络传输,又因为网络传输是很有可能被干扰到的,就有可能导致经过网络传输的数据的二进制从0变成了1,从1变成0,导致文件被修改,不能正确被读取出来。所以呢,redis自己肯定也会在读取这个文件的时候对这个文件进行校验,所以redis有一个工具就是专门来校验这个文件的。

在/usr/bin文件夹中有很多个redis相关的工具,其中校验RDB文件的工具就是redis-check-rdb,还可以看到有redis-check-aof,以及redis-server,redis-cli等等很熟悉的“工具”。


RDB自动触发保存的相关参数

在redis的配置文件中,可以看到,注意看红框框起来的就可以

这个的意思就是说,自动保存数据到硬盘的参数,save 秒数 修改次数,只有秒数和修改次数都满足才回去触发自动保存,下面就是900秒并且修改了1次,300秒修改了10次,60秒修改了10000次,只要满足这个三个条件中的一个呢,都会触发自动保存。

这里我们也可以想象到如果在两次保存之间,我一下子收到了很多指令,但是还没有来得及触发自动保存,redis就异常的挂了,那这些指令修改的数据,不就没有来得及去保存到硬盘中,那这些数据不就丢失了吗?这里我不是要将redis针对这些情况会怎么办,而是既然可能会有以上的情况会出现,是因为还没有来得及保存,那为什么手动修改配置文件自动保存的秒数和修改次数不就好了,直接修改了 save 1 1,产生一次修改1秒之后就去触发自动保存,不就行了吗?这当然是不行的,因为RDB自动保存是一个比较耗费资源的过程,频繁的触发自动保存,可能就会导致redis出现卡顿,消化不了其他客户端发来的指令,导致服务器崩溃,甚至更严重的事情。所以在生产环境上的修改RDB自动保存的参数一定是要根据实际情况来定的,争取是一个既能实现不影响redis的效率,也能够降低因为redis的数据来不及保存而丢失的情况出现。

2.2 RDB效果演示

这个一个完全保存没有任何键值对的RDB,目前我的redis也是没有保存任何数据的。

我插入三个键值对,再来看一下RDB文件有没有被修改呢?

如上图所示,我插入了三个键值对,而且也重新打开了这个RDB文件,可以看到RDB中保存的数据依旧是没变的,这个是因为什么呢?相信大家都想到了,因为还没有触发自动保存嘛,而且我也没有去手动会保存,所以RDB文件肯定还是原来的样子。这个时候,我们可以通过指令 save或者bgsave来吃手动触发保存,但是我们一般使用bgsave,而不是使用save,原因前面我也说过了。

看一下手动触发的效果

经过bgsave去手动触发保存呢,我们可以看到key1,key2,key3,但是其他数据是看不出来的,是因为是以二进制去保存数据的。

上面这种执行bgsave的方式是相当于我们手动保存,但是我们触发自动保存的三种方式

1.就是在M秒内产生了N次修改,就会触发自动保存更新RDB文件;

2.我们正常通过shutdown的方式关闭redis服务器,就是合法的方式去关闭redis服务器,在完全退出redis服务器之前的,redis也会自动触发保存RDB文件。

3.发生在主从复制到时候,主节点会自动保存一个RDB文件,并把RDB文件传递个子节点。关于主从复制这篇文章不会再讲,后面有机会会再出文章专门讲主从复制。

第一种触发方式我们就不演示了,主要来演示一下第二种方式

在已经有三个键值对的基础上,我再次插入一个键值对key4 444,这时候我们可以看到其实RDB文件欢迎更新。

现在我们通过指令 service redis-server restart,去重启一下redis服务器,再来看一下redis的RDB文件,可以看到RDB文件在redis正常重启是会自动触发RDB文件自动保存的。

但是现实中避免不了异常情况出现,比如redis服务器突然断电了,redis服务器进程突然掉了,就会因为来不及保存RDB文件而导致的redis的数据丢失。

如上图操作,我再次插入一个key5 555,然后我强制杀掉了redis的进程,可以看到其实redis服务器因为ubuntu的进程守护,又重新拉起了一个新的redis服务器进程,但是可以看到他的进程ID和杀掉的进程的ID是不一样,所以是重新开启了一个新的redis服务器进程。然后我们再次去看redis的内存中保存的全部键值对,key5这个键值对就已经是不见了的。这是因为突然的进程强制终止,导致redis服务器还没来得及执行RDB文件的保存操作,所以key5就没有被保存下来。

看到这里,相信我已经大概将RDB自动保存的过程说的比较明白了,大概过程就是子进程生成一个新的、临时的RDB文件,然后再将原来的RDB文件删除,让子进程新生成的RDB文件代替成为新的、唯一的RDB文件。子进程的过程我们是比较快的,我们也是没办法观察到的,那我们还可以怎么证明是真正的替换掉了原来的RDB文件呢?我们可以来看一下stat指令去看一下前后的RDB文件的INode编号,这个编号可以说是每一个文件的身份编号。

linux文件系统,也就是比较典型的文件系统的组织方式(etx4)主要是把文件系统分为三个大的部分:超级区(放一些管理信息),Inode(存放Inode节点,每一个文件都会被分配一个Inode数据结构,存放的信息就是文件的各种元数据),block区,存放的就是文件的数据内容了。

接下来看下面这张图,在插入键值对和执行bgsave之前的Inode编号是655889,执行bgsave之后,Inode是654407,所以dump.rdb的原信息确实是改变了,文件确实是产生了替换。

通过以上的说明,我们已经了解了RDB文件的生成以及重启之后redis服务器会去RDB文件用来恢复数据的过程。前面我们有说过如果我们不要去修改RDB文件的内容,但是还是会避免不了RDB文件可能会出错,导致redis服务器重启不了的情况。

接下来我们就去修改一下RDB文件的内容,观察一下是不是真的启动不了呢?如果我修改的是文件的末尾:

发现也没有启动不了啊,还是能够正常重启,并且能够查到键值对。这是因为我刚刚修改的是文件末尾的,所以redis还是可以识别到前面的数据的,虽然识别不到添加的数据,但是只是用来恢复数据的话,好像也不影响。实际不是的,redis服务器是带着毛病在运行的,虽然现在看不出来,但是如果我们再插入键值对又会怎么样呢?我们修改地地方是文件的中间,又会怎么样呢?现在我们就去修改rdb文件的中间的数据,比如直接删除掉文件的一般,

如上图,我在文件中间又插入一些1,我们再来重启一下redis服务器,看看是什么情况呢?你会发现Redis服务器就启动不了了。所以我们不要去修改RDB文件,不要故意的破坏它,特别是在生产环境上。

还有几个补充的点:

1.除了以上的几种方法会触发RDB文件自动保存,我们去使执行flushall删掉redis的内存中所有的数据的话,也会触发RDB去清空自己的数据,并自动保存。

2.redis配置中的,将 save 参数设置为空字符串(save "")会禁用 Redis 的默认 RDB(Redis Database)快照持久化机制。这是 Redis 官方支持的一种方式,用于完全关闭自动保存功能。

RDB的一个缺点就是两次自动保存之间的间隔可能会因为服务器断电而造成内存中的数据来不及保存而丢失。

3.AOF

而接下来要说的redis的另一种持久化的手段:AOF(append only file)就提供了一种对于RDB这个缺点的策略。AOF的策略就是实时的将操作redis的内存的指令全部以文本的形式记录到文件中,有点类似于mysql的binlog。也就是如果你增加一个键值对,aof记录的就是你增加了一个键值对这个事件,而不是具体的key和value,而且是实时的记录。然后启动的时候我们根据aof文件记录的操作去恢复数据到内存中,就可以避免因为断电来不及保存而造成的数据丢失。

MySQL 的 binlog(binary log) 是server层维护的一份二进制日志,与存储引擎无关。它记录了对数据库执行所有修改操作(INSERT/UPDATE/DELETE/DDL)的事件,不记录 SELECT。

AOF这个策略是默认关闭的,我们去可以配置文件文件手动开启,将下图的no该为yes就可以开启aof策略。下面是这个aof的文件名(可以手动配置),保存目录默认与rdb文件一致。

那既然开启了AOF策略,如果RDB记录的数据和AOF记录的数据有偏差怎么办呢?以AOF记录的为准,也就是说如果你开启了AOF策略,RDB文件就失效了,我们就以AOF记录的为准了,不回去考虑RDB记录的了。

3.1AOF实时写入文件的策略是否会影响redis的性能

为什么会有这个疑问呢?因为AOF是实时的写入到文件中,也就是redis服务器既要在把数据写入到内存,也要同时写入到AOF文件中,也就是还要操作硬盘,所以我们就担心每一次操作都要实时写入到硬盘会不会有影响redis的性能,毕竟写入硬盘的速度是要比写入内存要慢很多个数量级的。实际是不会的,主要原因就有两个:

1、redis对于要实时写入aof文件的数据提供了一个缓冲区aof_buf,也就是我们要缓冲区满足一定的条件才会要去写入要硬盘的aof文件的,这也很好理解,写入硬盘之所以慢不是受写入的数据的多少的影响并不大,而是受写入的次数的影响,之所以会觉得写入硬盘慢,是如果一条指令就要去写一次硬盘,那可能一秒就得必须去写入很多次硬盘,所以如果有一个缓冲区,我们就可以一次性的写入比较多数据。举个例子说明一个:如果磕一个瓜子就要把瓜子皮扔到厨房的垃圾桶的,扔完一个才能回到再磕一个,然后再去扔......,不觉得这样很不对劲吗?因为扔一个瓜子皮和扔一堆瓜子皮到垃圾桶花费的资源相差并不大,区别比较大的是要跑很多次。

2、对于写入硬盘的数据,redis还做了一个处理就是按照顺序写入,按照顺序读写,这个就要比随机读写要快不了。aof每次写入都是追加到文件末尾的,属于是按照顺序读写。

综合以上两个redis的处理方法,实时写入aof文件对redis的性能影响就比较低。

3.2 AOF缓冲区的刷新机制

前面说到AOF的实时写入前会先写入到缓冲区,缓冲区又是在内存中,那么如果考虑极端情况,还没来得及写入到硬盘的数据会不会丢失呢?实际上,确实会,但是这并没有办法,世上没有两全的法,既要实时写入,又要保证数据不丢失,很难。所以我们只能针对于实际场景去选择更好的策略,更好的减少损失。说会AOF缓冲区的刷新机制,就是我们要按照什么策略去刷新缓冲区,将缓冲区的数据写入到硬盘中,按照什么样子的频率呢?redis也提供了三个给我们选择

always:命令写入就去同步到aof文件。刷新频率最高,数据安全性最高,性能最低;

everysec:刷新频率适中,数据安全性适中,性能也是适中。

no:这个就是不主动设置刷新的策略了,只有操作系统去决定,redis是安装在Linux,那就是有Linux操作系统去决定,如果他要让缓冲区写满了再去写入或者怎么样的策略都好。这个策略刷新频率就更低了,数据安全性也最低,但是redis的性能最高。

综合以上三种策略,我们都可以在redis的配置文件中去进行配置,综合起来,我们更会选择everysec,虽然没有always的最高数据安全性,也没有no的最高性能,但是有比较好的性能和数据安全性。当然这还是得考虑实际情况,如果就是更关注数据安全,不那么重视redis的性能,就可以去选择always,如果就要性能最佳,数据安全性不关注,不那么重要,就可以选择no。更通常的情况确实是选择everysec,因为现在随着硬件的更新迭代,写入硬盘的速度确实是可以提升不少,随意即使是每秒写入,速度可以很快了,同时又能兼顾到数据安全。

3.3 AOF的重写机制

现在我们又有问题要考虑了,会不会因为我们不断的写入数据到AOF文件中,导致AOF文件越来越大,毕竟如果开启了aof机制,redis每次启动都必须去读取aof文件,用来恢复数据到内存,如果aof文件特别大,那redis的启动速度不就变得很慢吗?可能你已经猜到,我都怎么说了,那就是肯定不会啦。我先说重点:redis会对aof文件去冗余操作。先来考虑一下几种情况,能够比较好理解怎么个去冗余法。

set key 111

set key 222     ------->   set key 333

set key 333

lpush key1 111 

lpush key1 222  ------->   lpush key1 111 222 333

lpush key1 333

set key2 111

del key2                 ------->相当于啥也没做

set key2 222

del key2

如上面的情况,有时候我们会产生很多无效的记录,所以AOF文件最终记录的是内存中数据最终转态,不去关注中间过程,这样子,AOF的文件就不会那么大了,跟RDB文件差不多。接下来我们就来仔细的聊一聊AOF的重写机制,到底AOF文件是如何写入和保存的,机制到底是怎么样的,是如何比RDB更好的保存数据的。

3.4 AOF文件的保存也是两种触发方式:

手动触发:通过指令bgrewriteaof

自动触发:根据配置的两个参数 auto-aof-rewrite-min-size和auto-aof-rewrite-precentage参数确定自动触发。auto-aof-rewrite-min-size指的是当aof的大小达到多大MB就触发,默认是64MB;auto-aof-rewrite-precentage指的是当aof文件的大小达到上一次重写时增加的比例就触发自动保存。

下面这种图就很好的描述了AOF的重写机制

1、当执行bgrewirteaof命令的时候,父进程会先去看当前有没有子进程在指令这个指令,有的话就会直接返回,让原先的子进程去继续执行aof的重写。

2、如果当前没有子进程在执行指令bgrewriteaof的话,父进程依旧会调用frok指令去创建一个子进程,关于这个子进程是怎么样的,前面已经有说过了,就是子进程会有一个和父进程一样的内存空间,当然也是页表。

3、当子进程被创建的时候,子进程是去生成一个全新的aof文件,而且并不说是去遍历旧的aof文件,然后去将旧aof文件的数据都写入到新的aof文件,这样子完全没有意义,实际上子进程是根据此时内存的数据去生成的,就像我们前面说到会对数据去冗余操作,就是体现在这里,只要将内存的数据如实的记录到新的aof文件中,就相当于去冗余操作了。(这里还有一个注意的点,后面会进行演示是再说明。)

4、仔细看上图,除了有前面说到的aof_buf之外,还有一个aof_rewriter_buf,这也是个缓冲区,那这个缓冲区是干嘛的呢?从上面的描述我们不难看出,还有一个问题,子进程只能记录fork之前的内存数据,对于fork之后的数据,子进程是完全没有感知的,因为在子进程完成aof文件的重新的时候,父进程依旧会继续去处理客户端的指令,在这个过程,势必就会产生很多新的数据,如果对于新产生的数据不去写入到新的aof文件的,当新的aof文件去替换旧的aof文件的会,这其中的数据就会丢失了。所以我们还需要一个aof_rewriter_buf,父进程在将数据写入到aof_buf的时候,也会写入一份到aof_rewriter_buf缓冲区,这个缓冲区的数据是给子进程用的,但子进程第一次完成重写aof文件的时候,会通过信号去通知父进程自己完成了文件的重新,这时候,父进程就会把aof_rewriter_buf缓冲区的数据拼追加到子进程的重写新的aof文件,然后再用新的aof文件替换旧的aof文件,这样就能够保证新的aof文件和旧的aof文件记录的数据是一致的,避免了数据的丢失。

4.还有两个问题

1、如果执行bgrewriteaof之后,发现正在生成RDB快照怎么办呢?

        等待RDB快照生成,再去执行bgrewriteaof的后续动作。

2、旧的aof文件还有必要继续写入吗?

        为什么会有这个疑问呢?主要是如果有aof_rewrite_aof和子进程的新aof文件,不就可以保证了这两者生成的aof文件就能代表内存当前数据的最新状态了吗?话虽然如此,但是还是要考虑极端情况,如果新AOF文件保存,服务器掉电了,或者被强制杀掉了,那么子进程的内存数据就被释放了,新的aof文件也只是保存一半,是不完整的,是不能够使用的,如果这时候没有旧的AOF文件,那数据不就全都丢失了吗。所以旧AOF文件的存在就是为了防止这种情况的发生了,即使我们已经马上就有了新的AOF文件了,旧的AOF文件也要好好维护,不然可能到最后一无所有。就像我们跳槽一样,即使你已经正在办理离职交接手续,马上就去取新公司了,如果在最后的这段时候不好好表现,一但新公司毁约,原先的公司一看你表现不行,也不要了,那不就全没了吗?所以旧的AOF文件也是要好好维护的,存在就有一定的意义。

5. Redis的混合持久化

我们可以先来看一下重启之后的,还没有去写入新的数据到内存的AOF文件是怎么样的,以及此时的RDB文件是怎么样的呢?看一下这个aof文件的内容,像不像rdb文件呢?

但是如果我再添加键值对,aof文件又是怎么样的呢?是以文本的方式,追加到文件末尾。

其实可以看到这两个图是有一样的,是因为redis默认开启了混合持久化,这个机制就发生在子进程将内存中的数据写入到新的aof文件的时候,本来aof写文件的方式确实是用文本的方式,但是发现这样加载文件太慢了,所以,在触发aof重写的时候,就会按照RDB的方式就内存中的数据按照二进制的方式写入到aof文件中,但是在重启之后,主进程还是会将操作的事件或者说指令以文本的方式写入到旧的aof文件中,看到这里你可能会有疑问。那aof_rewrite_buf的操作是以什么样的形式写入到新的aof文件的呢?缓冲区的数据是以文本的形式追加到新的aof文件的末尾的。

http://www.dtcms.com/a/490729.html

相关文章:

  • 网站建设进度深圳网站建设制作营销
  • SSM高校学生社团管理系统n4pcu(程序+源码+数据库+调试部署+开发环境)带论文文档1万字以上,文末可获取,系统界面在最后面。
  • 强化学习_Paper_2000_Eligibility Traces for Off-Policy Policy Evaluation
  • Kubernetes秘钥与配置管理全解析
  • Python 匿名函数、map、filter、sort 用法详解
  • wordpress 4.0 伪静态seo优化一般优化哪些方面
  • 上海自助模板建站wordpress被黑
  • 数据可视化延迟实时大屏优化:WebSocket增量传输+Canvas渲染数据延迟压缩至300ms
  • TimerFd Epoll
  • 百度网盘怎么实现不限速的高速下载?
  • UltraEdit做网站教程定制开发网站如何报价单
  • 《彻底理解C语言指针全攻略(5)--指针和函数专题》
  • 广州做网站找哪个公司好建设网络道德教育网站不包括
  • TUP及ESOP动态股权激励:算法是核心
  • 数据库知识全解析:从基础概念到MySQL实战
  • Python - 100天从新手到大师:第五十七天获取网络资源及解析HTML页面
  • PLY文件格式讲解与可视化展现方式(基于Viser库)
  • 中山百度网站排名织梦播放器网站
  • 珠海建站网站兰州模板网站seo价格
  • jQuery面试题精选:从基础到高级
  • 计算机操作系统:死锁概述
  • C++之理解共用体
  • Java Spring配置
  • 【多进线程】python多进线程与通信
  • 低代码新建表单实操:纯表单 / 列表表单配置 + 表名避坑
  • 前端做数据表格的网站网站建设与运营市场风险
  • 从入门到精通:深度探索RT-Thread物联网操作系统
  • GPUStack:开源GPU集群管理工具,解锁AI模型高效运行新可能
  • LeetCode算法日记 - Day 74: 按摩师、打家劫舍II
  • centos离线包获取-附centos7主流离线包资源