Redis持久化篇

持久化篇

1、AOF持久化是怎么实现的?

1.1、AOF日志

在这里插入图片描述

​ 保存写操作到日志的持久化方式,就是Redis里的AOF持久化功能,注意只会记录写操作,读操作命令是不会被修改的,因为没有意义。=> 需要修改redis.comf里的参数:appendonly yes && appendfilename “appendonly.aof” 分别表示是否开启AOF持久化,AOF持久化文件的名称。

​ AOF文件格式 *3代表三部分 $3代表命令的字节数位3字节

而且Redis是先执行写操作,再记录命令到日志,这样有两个好处:

​ 1)避免额外的开销,如果写操作语法有问题,记录到AOF日志,恢复的时候可能会出问题。

​ 2)不会阻塞当前写操作命令的执行

风险:

​ 1)redis还没来得及将命令写入到硬盘,服务器宕机,数据就会有丢失的风险

​ 2)写操作命令执行成功后才记录AOF体制,所以不会阻塞当前命令的执行,但是可能给下一个命令带来阻塞风险,因为写入内存和写入磁盘的命令都是主进程完成的

1.2、三种写回策略

​ 用户态(执行写操作命令 -> 命令追加到server.aof_buf)—— I/O系统调用write —— 内核态(内核缓冲区page cache -> 由内核发起写操作 -> 硬盘)

具体实现步骤:

1、Redis执行完写操作后,会将命令追加到server.aof_buf缓冲区

2、通过write()系统调用,将aof_buf缓冲区的数据写入AOF文件,此时数据没有写入到磁盘,而是拷贝到内核缓冲区page cache,等待内核将数据写入硬盘;

3、具体内核缓冲区的数据什么时候写入到硬盘,由内核决定。

写回磁盘策略 => redis.conf配置文件中的appendsync三种参数可以填

1、Always:总是,每次执行完写命令操作后,同步将AOF日志数据写回磁盘

2、Everysec:每秒,每次执行完写操作后,现将命令写入到AOF文件到内核缓冲区,每隔一秒将缓冲区的内容写回磁盘

3、NO:交给操作系统,命令写入AOF内核缓冲区,由操作系统决定什么时候写回磁盘

在这里插入图片描述

​ 这三种写回策略其实就是什么时机执行fsync()函数,Always每次写入就执行;Everysec创建一个异步任务来执行;No就是永不执行。

1.3、AOF重写机制

​ AOF日志是一个文件,随着写操作命令越来越多,文件的大小会越来越大 => 为了避免AOF文件越写越大,提供了AOF重写机制,文件大小超过设定的阈值之后,Redis会启动AOF重写机制来压缩AOF文件。

​ 具体的做法是:读取当前数据库中的所有键值对,将每一个键值对用一条命令记录到新的AOF文件中,等到全部记录完之后,将新的文件替换到现在的AOF文件。相当于记录对某个键的最新值,删除掉旧值,减少了AOF日志的大小,所以重写需要重写到新的AOF文件中,失败的话,直接删除这个文件就好,不会对现有的AOF文件造成影响。

1.4、AOF后台重写

​ 重写的时候,这个过程是比较耗时的,所以重写的操作不能放在主进程里 => 重写AOF过程是由后台子进程bgwrriteaof来完成的,有两个好处:

​ 1)子进程重写AOF期间,主进程可以继续处理命令请求,从而避免阻塞主进程;

​ 2)子进程带有主进程的数据副本,注意不是线程,线程共享内存,会在修改共享内存数据的时候加锁,影响性能,而父子进程共享内存数据,以只读的方式,当父子进程任意一方修改了该共享内存,就会发生写时复制,于是父子进程就有了独立的数据副本,不需要加锁也可以保证数据安全。

实现过程

1、主进程fork()系统调用生成bgrewriteaof子进程,页表复制给子进程(虚拟地址和物理地址的映射关系),共享物理内存,内存的权限为可读

在这里插入图片描述

2、当父进程或子进程向这个内存发起写操作时,CPU就会触发写保护中断,进行物理内存的复制,重新设置映射关系,父子进程的内存读写权限设置为可读写,最后才对内存进行写操作 => 写时复制

在这里插入图片描述

3、存在两个阶段导致父进程阻塞:1)创建子进程,复制页面,页面太大,阻塞时间长;2)子进程或父进程修改共享数据,发生写时复制,拷贝物理内存,阻塞时间长。

4、可能出现的问题:

​ 1)在写时复制阶段,修改的是一个bigkey(数据量比较大的key-value),这个时候复制的物理内存数据的过程会比较耗时,有阻塞主进程的风险。

​ 2)主进程修改key-value,但是在子进程内存数据跟主进程数据不一致 => 设置AOF重写缓冲区,这个缓冲区在创建bgrewriteaof子进程就开始使用

在这里插入图片描述

​ 2)当子进程完成AOF重写工作的时候,发送信号给主进程 => AOF重写缓冲区的所有内容追加到新的AOF内容中,使得新旧AOF文件的数据库状态保持一致;将新的AOF文件进行改名,覆盖现有的AOF文件。

2、RDB快照是怎么实现的?

​ AOF文件的内容是操作命令(不是实际数据)、RDB文件的内容是二进制数据(某一个时刻的数据库实际数据);RDB恢复数据的效率比AOF高些,因为RDB文件读入内存就行,而AOF需要额外的执行操作命令步骤才能恢复数据。

2.1、快照怎么使用

1)save 命令,在主线程生成RDB文件,由于和执行操作命令在同一线程,所以如果写入RDB文件的时间太长,会阻塞主进程。

2)bgsave 命令,会创建一个子进程来生成RDB文件,这样避免主线程阻塞。

=> 可以配置每隔一段时间自动执行一次bgsave命令

save 900 1  // 900秒内,对数据库至少进行一次修改
save 300 10 // 300秒内,对数据库至少进行10次修改
save 60 10000 // 60秒内,对数据库至少进行10000次修改

2.2、执行快照时,数据能被修改吗?

可以的! => 关键技术:写时复制

​ 1)当主线程(父进程)对这些共享的数据只进行读操作的时候,是互不干扰的

​ 2)当主线程执行写操作的时候,就会发生写时复制,该数据块的物理内存就会被复制一份,然后主线程在这个数据副本进行修改操作,bgsave会在原来的数据写入到RDB文件。

​ 所以这样意味着子进程写入到RDB文件的数据只能是原本的内存数据,修改的部分交由下一次bgsave快照。

​ 极端情况:刚fork时,途中主进程处理了写操作,修改了共享内存,修改的数据的内存会被复制一份 => 极端情况下,内存的占用时原来的两倍。

2.3、RDB和AOF合体

​ RDB尽管数据恢复速度快,但是频率不好把握。

​ 1)频率太低,两次快照间一旦服务器发生宕机,就可能丢失较多数据;

​ 2)频率太高,频繁的写入磁盘和创建子进程会带来额外的性能开销。

=> 混合使用AOF日志和内存快照,亦称混合持久化 aof-use-rdb-preamble yes,工作在AOF日志重写过程

具体的做法是:(前半部分是RDB格式的全量数据 + 后半部分AOF格式的增量数据)

​ 1)AOF重写日志的时候,fork出来的重写子进程会先将与主线程共享的内存数据以RDB方式写入到AOF文件;

​ 2)然后主线程处理的操作命令会被记录在重写缓冲区里,重写缓冲区里的增量命令会以AOF方式写到AOF文件;

​ 3)写入完成后,将含有RDB格式和AOF格式的文件 替换 旧的AOF文件

3、Redis大key对持久化有什么影响?

3.1、大Key对AOF日志的影响

1、三种写回策略,在持久化大Key的时候,会有什么影响?

  • Always策略的时候,如果写入的是一个大Key,主线程在执行fsync()函数的时候,阻塞的时间会比较久,因为当写入数据量很大的时候,数据同步到硬盘这个过程是很耗时的。
  • Everysec策略,由于是异步执行fsync()函数,所以大key持久化过程不会影响到主线程。
  • No策略,永不执行fsync(), 所以大key持久化过程不会影响到主线程。

3.2、大Key对AOF重写和RDB的影响

​ 当AOF日志写入很多大Key,AOF日志文件的大小会很大,很快就会触发AOF重写机制。

​ AOF重写机制和RDB快照都会分别通过fork()函数来创建一个子进程来处理任务。

​ => info命令可以获取到latest_fork_usec指标,表示Redis最近一次fork操作的耗时,如果fork耗时很大,如超过1s需要做出调整

​ 1)单个实例的内存占用在10GB以下,fork很快就能返回

​ 2)Redis单纯做缓存,不关心Redis数据安全性问题,直接关闭AOF重写

​ 3)在主从架构,适当的调大repl-backlog-size,避免主节点频繁的使用全量同步的方式。

1、什么时候发生物理内存的复制?

​ 1)创建子进程途中,要复制父进程页表等数据结构

​ 2)当父进程或子进程向共享内存发起写操作,CPU就会触发写保护中断,写时复制

2、linux开启了内存大页,会影响redis性能

3、删除大key

​ 使用unlink命令(异步不阻塞),而不是用delete(会阻塞主进程)

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

Coder陈、

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

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

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

打赏作者

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

抵扣说明:

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

余额充值