欢迎来到尧图网

客户服务 关于我们

您的位置:首页 > 汽车 > 时评 > 关于Redis的持久化

关于Redis的持久化

2025/2/8 19:49:18 来源:https://blog.csdn.net/m0_73629312/article/details/145328257  浏览:    关键词:关于Redis的持久化

目录

RDB

  1.手动触发

   2.自动触发

AOF 

aof的重写机制


Redis虽然是一个内存数据库,但是也是可以将数据存储到硬盘中的,也就是持久化。硬盘的数据是在Redis重启的时候,用来恢复内存中的数据的,即对数据做了一个备份。Redis实现持久化具体是按照RDBAOF两种策略来实现的。当同时开启RDB和AOF的时候,以AOF为主。

RDB

   即Redis database,是指定期把Redis中的数据写入硬盘中,生成一个“快照”,存储在硬盘中。后续Redis一旦重启了(内存数据没了),就可以根据刚才的“快照”把内存中的数据恢复回来。

redis加载RDB恢复数据的速度远远快于AOF的方式,因为RDB是用二进制的方式来组织数据的,AOF是使用文本的方式组织数据的。

  “定期”具体说来,又有两种方式:

  1.手动触发

      程序员通过redis客户端,执行特定的命令,来触发快照生成。

       主要有两个命令:

        save:redis会全力以赴的生成“快照生成”的操作,此时就会阻塞redis的其他客户端的命令。会直接在当前进程中,往同一个rdb文件中写入数据。

        bgsave:bg => background(后面),不会影响redis服务器处理其他客户端的请求和命令。此处redis使用的是“多进程”的方式,来完成并发编程。流程如下

        1.判定当前是否已经存在其他正在工作的子进程。如果当前已经有一个子进程正在执行bgsave,此时就直接把当前的bgsave返回。

        2.如果没有其他的工作进程,就通过fork这样的系统调用创建出一个子进程。fork是linux系统提供的一个创建子进程的api。fork创建子进程直接把当前的进程(父进程)复制一份,作为子进程,子进程的内存里会存储和父进程一样的数据。一旦复制完成了,父子进程就是两个独立的进程,就各自执行各自的了。接下来安排子进程去执行“持久化”操作。

        3.子进程负责进行写RDB文件,生成快照的过程。父进程继续接收客户的请求,正常提供服务。

        4.子进程完成整体的持久化过程之后,会通知父进程,父进程就会更新一些统计信息。子进程就可以结束销毁了。

       注: rdb持久化操作可以触发很多次。当执行生成rdb镜像操作的时候,此时就会把要生成的快照数据,先保存到一个临时文件中。当这个快照快要生成完毕的时候,再删除之前的rdb文件,把新生成的临时的rdb文件名字改成dump.rdb。就可以保证自始至终,redis中的rdb文件只有一个。

        

   2.自动触发

  自动触发即在Redis配置文件中设置一下,让Redis每个多长时间/每产生多少次修改,就触发。 

  在redis的官方配置文件redis.conf中,关于RDB自动触发的机制是:

save <seconds> <changes>
save 900 1
save 300 10
save 60 10000

   seconds代表触发所需的秒数,changes表示在seconds时间内,内存中key修改的次数。save 900 1 表示在900s内至少存在一次key的修改,则在900s后会执行备份。

  以上的数值都可以修改。但是我们的原则是不能让快照操作执行的太频繁。

注:1.不仅仅是save执行一定时间内修改n次的方法,通过shutdown命令(关闭redis服务器的命令)也能触发生成快照。

2.  当redis进行主从复制的时候,主节点也会自动生成rdb快照,然后把rdb快照内容传输给从节点。

3.  save ""  表示关闭自动生成快照。

如果通过以上正常流程重新启动redis服务器,此时redis服务器会在退出的时候,自动触发生成rdb操作。但是如果是异常重启(kill -9 或服务器掉电)此时redis服务器来不及生成rdb,内存中尚未保存到快照中的数据,就会随着重启而丢失。


AOF 

  RDB的最大问题,在于不能实时的持久化保存数据。在两次生成快照之间,实时的数据可能会随着重启而丢失。

AOF(append only file) 会把用户的每个操作,都记录到文件中。当redis重新启动的时候,就会读取这个aof文件中的内容,用来恢复数据。

当开启aof的时候,rdb就不生效了。aof默认是关闭状态,修改配置文件来开启aof功能。

AOF并不会影响到redis处理请求的速度,原因:

1. AOF机制并非是直接让工作线程把数据写入硬盘,而是先写入一个内存中的缓冲区,积累一波之后,再统一写入硬盘。

2. 硬盘上读写数据,顺序读写的速度是比较快的,随机访问的速度是比较慢的。AOF是每次把新的操作写入到原有文件的末尾,属于顺序写入

由于缓冲区是在内存中,如果主机突然掉电,数据就会丢失。redis给出了一些选项,让程序员根据实际情况来决定如何取舍,也就是缓冲区的刷新策略,刷新频率越高,性能影响就越大,同时数据的可靠性就越高。

always相当于立即刷新,频率最高,数据可靠性最高,性能最低。

everysec 相当于每秒刷新。

no相当于由操作系统自行决定刷新频率。频率最低,数据可靠性最低,性能最高。

默认策略是everysec。

aof的重写机制

redis启动的时候要读取aof文件的内容,但是aof文件中的内容可能存在冗余。redis就存在一个机制能够针对aof文件进行整理操作,这个机制就是能够剔除其中的冗余操作,并且合并一些操作,达到给aof文件瘦身的效果。也就是重写机制(rewrite)。

重写机制的触发方式分为手动触发自动触发

AOF重写的流程

  使用fork的方式创建子进程,父进程仍然负责接收请求,子进程负责针对aof文件进行重写。而此时内存中的数据的状态,就已经相当于是把AOF文件结果整理后的模样了。所以子进程只需要把内存中当前的数据获取出来,以AOF的格式写入到一个新的AOF文件中。

  非常类似于RDB生成快照的过程,只不过RDB是按照二进制的方式生成的。AOF则是按照AOF这里要求的文本格式来生成的。

在子进程写新aof的同时,父进程仍然在不停的接收客户端新的请求。父进程还是会先把这些请求产生的AOF数据先写入到缓冲区再刷新到原有的AOF文件中。

在创建子进程的一瞬间,子进程就继承了当前父进程的内存状态。因此,子进程里的内存数据是父进程fork之前的状态。fork之后,新来的请求对内存造成的修改,是子进程不知道的。

此时,父进程这里又准备了一个aof_rewrite_buf缓冲区,专门放fork之后收到的数据,专门往新的aof文件去写。

子进程这边,把aof数据全部写完之后,会通过信号通知父进程。父进程再把aof_rewrite_buf缓冲区中的内容也写入到新AOF文件在里。

然后就可以用新的AOF文件代替旧的AOF文件了。

问题:

1、如果,在执行aof_rewrite_buf的时候,当前redis已经在进行aof重写了,会怎样呢?

此时,不会再次执行aof重写,直接返回了。

2、如果,在执行aof_rewrite_buf的时候,发现当前redis在生成rdb文件的快照,会怎样呢?

此时,aof重写操作就会等待,等待rdb快照生成完毕之后,再进行执行aof重写。

3、为什么rdb不在fork之后,也采用类似aof_rewrite_buf缓冲区的方式来处理新数据呢?

rdb本身的设计理念,就是用来“定期备份”的。之要是定期备份,就难以和最新的数据保持一致。

4、父进程在fork后,继续写这个即将消亡的旧的aof文件是否还有意义?

考虑到极端情况,假设在重写到一半的时候,服务器突然掉电,子进程内存的数据就会丢失,新的aof文件内容还不完整,所以如果父进程不坚持写旧aof文件,重启就没法保持数据的完整性了。

以上,关于redis,希望对你有所帮助。

版权声明:

本网仅为发布的内容提供存储空间,不对发表、转载的内容提供任何形式的保证。凡本网注明“来源:XXX网络”的作品,均转载自其它媒体,著作权归作者所有,商业转载请联系作者获得授权,非商业转载请注明出处。

我们尊重并感谢每一位作者,均已注明文章来源和作者。如因作品内容、版权或其它问题,请及时与我们联系,联系邮箱:809451989@qq.com,投稿邮箱:809451989@qq.com