Redis的持久化选择AOF or RDB,以及选择策略

持久化的作用:

为什么要进行持久化?对于redis来说,因为它是一个内存数据库,数据都放在内存中,如果没有持久化机制,那么当机器重启或者redis宕掉后,数据都会丢失,这样对于我们来说是无法容忍的,所以接下来我们来介绍redis的两种持久化机制AOF 和RDB。

RDB(Snapshot)

RDB是redis根据触发方式在某个时间点将数据库中的数据以二进制格式保存到磁盘当中,生成的文件是rdb格式。即rdb相当于数据库某个时间点的快照。下次redis重启后会读取rdb文件到内存然后进行数据恢复。

如何触发RDB

RDB三种触发方式

1:save(同步)
2:bgsave (异步)
3:Auto (自动进行)
分析第一个save,在客户端执行save命令,那么redis主进程会去执行rdb文件的生成,此时其他客户端发送来的操作数据库的命令都会被阻塞,这样会对redis的性能会造成极大的影响,每次生成rdb文件都会在指定数据目录下生成临时文件,等到新的rdb文件生成后会覆盖掉原来的rdb文件,因为阻塞对性能的影响,不推荐这种方式。
bgsave:执行此命令时,redis会调用linux的fork函数,即单独开一个线程去执行rdb文件的生成,这样就不会阻塞redis线程,也可以执行其他客户端的命令。同样的每次生成rdb文件都会在指定数据目录下生成临时文件,等到新的rdb文件生成后会覆盖掉原来的rdb文件。但是我们要注意的是redis执行fork()函数创建子线程的时候,它是阻塞的
save与bgsave的优缺点:
save不会消耗额外内存,bgsave执行fork()函数,需要消耗额外内存
save会阻塞客户端命令,但是bgsave只有在执行fork创建子线程的时候会阻塞主线程,bgsave不会阻塞客户端,但是这里要强调的是无论执行save还是bgsave,其时间复杂度都是o(n),会遍历数据库的全部数据,同时这两个命令很重,即RDB是一个很重的方式,需要把全部数据写到磁盘,对于磁盘性能的消耗是很大
自动生成RDB方式:下图为redis默认自动生成策略
即在900s内有1次修改会生成rdb文件,在300s内有10次修改会生成rdb文件
在60s内有10000内会生成rdb文件。任意一个条件达成都会执行rdb操作。
在这里插入图片描述rdb相关参数配置
在这里插入图片描述第一个参数:再出现bgsave写错误后是否继续执行继续写bgsave操作
第二个参数:是否开启生成压缩的rdb文件
第三个参数:是否开启rdb校验和。
第四个参数:指定rdb文件名称。

RDB隐藏触发方式

1:在执行主从全量复制时,会生成rdb文件
2:debug reload :以debug方式的重启。不需要清空内存的重启
3: shutdown 关闭服务器的时候,会进行落盘操作。

bgsave验证

实验前提:db里有很多的数据,能够让bgsave的执行有一段时间
验证:
1:bgsave执行时会创建redis的子进程
2:bgsave执行时会创建一个临时文件,生成后会删掉原来的rdb文件
3:bgsave不阻塞客户端执行

验证步骤
1:在未执行bgsave命令时有关redis的进程只有一个server主进程
在这里插入图片描述启动bgsave
在这里插入图片描述
在这里插入图片描述执行命令:发现没有阻塞
在这里插入图片描述同时立即观察进程:发现出现bgsave子进程
在这里插入图片描述当完成bgsave时进程消灭:
在这里插入图片描述执行bgsave还未完成时,观察data目录,生成临时文件,最后会替换之前的rdb文件
在这里插入图片描述执行bgsave后观察data目录后:
在这里插入图片描述

AOF:

之前分析过rdb返现它的缺点很明显,消耗性能,并且耗时(O(N)复杂度,损耗磁盘性能,fork()消耗内存,写时复制策略消耗内存),不可控制,丢失数据(比如下图所示)

T1执行多个写命令
T2满足rdb创建条件
T3再次执行多次写命令
T4宕机

这样就会造成T3时刻命令丢失。

写时复制

写时复制:
父子进程会共享相同的物理内存页,当父进程处理写请求时会把要修改的页创建副本,而子进程在fork操作过程中共享整个父进程内存快照,相当于感知不到父进程创建的副本,等到重写完成后,会把副本的链接替换掉原来的内存页,所以如果在aof重写期间,有大量的写请求过来,会创建大量的内存页副本,对于内存开销会很大。

写时复制详细原理
fork子进程,fork这个瞬间一定是会阻塞主线程的,fork采用操作系统提供的写实复制(Copy On Write)机制,就是为了避免一次性拷贝大量内存数据给子进程造成的长时间阻塞问题,但fork子进程需要拷贝进程必要的数据结构,其中有一项就是拷贝内存页表(虚拟内存和物理内存的映射索引表),这个拷贝过程会消耗大量CPU资源,拷贝完成之前整个进程是会阻塞的,阻塞时间取决于整个实例的内存大小,实例越大,内存页表越大,
fork阻塞时间越久。拷贝内存页表完成后,子进程与父进程指向相同的内存地址空间,也就是说此时虽然产生了子进程,但是并没有申请与父进程相同的内存大小。那什么时候父子进程才会真正内存分离呢?
“写实复制”顾名思义,就是在写发生时,才真正拷贝内存真正的数据,这个过程中,父进程也可能会产生阻塞的风险 -----引用自kaito
fork的子进程先拷贝父进程的页表,然后完成后,子进程与父进程指向相同的内存地址空间,在真正进入aof重写的情况,才会申请与父进程相同的内存大小然后将页表指向的内存数据拷贝过来。

AOF运行原理

Aof文件中保存了我们执行对于数据库状态修改的命令,每次aof重启后都会
读取aof文件,读取其中命令重新执行恢复数据库数据状态。

AOF三种策略

1:always
2:everysec
3:no
下面图详细描述了三种策略:

在这里插入图片描述在这里插入图片描述在这里插入图片描述三种方式的优缺点:

1:always:不会丢失数据,但是对磁盘性能消耗较大,因为没执行一次命令,都会执行刷盘操作。
2:everysec(推荐):每隔1s进行一次刷盘操作,对比always对磁盘有了一定的保护。会丢失1s的数据
3:no:由os来决定什么时候进行刷盘操作,我们不可控。

AOF重写

引入aof重写的目的是减少磁盘的使用量,加快恢复速度,在下面这样一个场景
执行 incr key 一万次,这样在aof文件中,就会把这条命令写1万次,这样没有任何意义,也会使得aof文件变得臃肿庞大,和执行set key 10000效果是一样的,同时sadd key a,sadd key b, sadd key c客户以合并成一条命令:sadd key a b c 执行这样一条语句的效果和上面执行三条语句的效果是一样的,所以引入aof重写就是为了解决上诉问题,对aof文件进行优化。

aof动态开启策略:

在这里插入图片描述

AOF重写实现方式:

bgrewriteaof命令:同bgsave命令一样,通过fork函数启动子线程来执行aof重写。
注意aof重写并不是分析原先旧的aof文件,然后优化生成新的aof文件,而是从内存当中数据分析进行aof重写,生成新的aof文件

AOF重写配置

//aof文件重写需要的尺寸(字节)
auto-aof-rewrite-min-size
//aof文件增长率
 auto-aof-rewrite-percentage  
 //aof文件现在的尺寸(字节)
 aof_current-size
 //aof上次启动和重写的尺寸(可以执行info persistence命令可见)
 aof_base-size
 //代表是否忽略aof中数据不完整部分,比如写aof写到最后,忽然宕机了,即
Aof没有写完整。 
 aof-load-truncated yes

在这里插入图片描述info peisistence(有关rdb与aof相关信息):RDB and AOF related information
在这里插入图片描述

aof重写流程:
在这里插入图片描述开启no-appendfsync-on-write yes时的aof重写流程,该参数表示aof重写时是否追加到aof缓冲区
在这里插入图片描述上图有一处错误:应该是aof重写缓冲区,这里重新描述一下aof缓冲区与aof重写缓冲区之间的差别

AOF缓冲区与AOF重写缓冲区。

在aof重写期间,redis服务器在执行一个写命令后,会同时将这个写命令发送给AOF缓冲区与AOF重写缓冲区。
未进行aof重写期间,写命令只会发送到aof缓冲区。
AOF缓冲区中的内容会定期(everysec,always,no)被写入和同步到AOF文件中。对现有aof
文件的处理工作会照常进行。而从创建子进程开始,服务器执行的所有写命令都会被记录到AOF重写缓冲区里面,当子进程完成aof重写工作后,将aof重写缓冲区中的所有内容写入到新AOF文件中,这时新AOF文件所保存的数据库状态将和服务器当前的数据库状态一致。
AOF重写缓冲区的必要性:如果没有的话,那么当aof缓冲区还没有刷盘的情况下,开启aof重写,那么aof缓冲区的内容就会冗余。

aof文件格式:

在这里插入图片描述

RDB与AOF相互取舍所需要的考虑的?

在这里插入图片描述
RDB重是因为每次保存的是数据库的全部数据,写入磁盘对磁盘性能影响较大,而aof较轻因为通过追加命令的操作,在加上通过aof重写,所以较轻。

推荐策略:

推荐主节点关闭RDB,从节点开启RDB,然后都开启AOF,保存策略:everysec

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值