回忆Redis的持久化机制

Redis的持久化机制

前言

大家都知道,Redis是内存数据库,也就是说client与Redis交互的过程,无论是读key还是写key都是直接访问Redis的内存即可,但对于宕机备份容灾等问题,就需要引入持久化,Redis提供RDB或AOF,还有从版本4.0开始引入这RDB和AOF两种的混合持久化方式。

RDB

RDB持久化是通过创建快照来获取内存某个时间点上的副本,所以重启redis时利用快照可以方便恢复,默认快照文件为dump.rdb。

触发方式

配置方式

通过配置每隔n秒有m个key发生变化,即会触发,生成一次RDB;

手动触发

可操作save和bgSave命令(默认bgSave),生产上应该用bgSave,因为相比save只用主线程进行RDB,后者是fork一个子进程来进行,避免阻塞主线程执行client的操作命令。

bgsave的执行流程

①首先检查是否有在执行RDB或AOF的子进程在执行,如果有就返回错误;

②此时触发RDB,调用的是rdbSaveBackgroud;

③开始fork子进程,同时主进程继续执行client的发送的操作命令;

④RDB完成后,会替换为新的dump文件,子进程停止;
其中关于fork子进程,会阻塞主线程微秒级别的性能,阻塞也不是直到fork子进程结束,而是为了加快它fork子进程的效率,使用到写时复制的机制;

写时复制的意思是,操作系统中进程访问内存,是每个进程都有自己的虚拟内存(例如32位最大虚拟内存为4G),然后通过页表中绑定物理内存的关系来映射物理内存,如果进程没有虚拟内存访问物理内存,则会发生缺页异常,所以bgsave在fork子进程时,只是将主线程所在进程访问物理内存的页表复制一份,将它设置为可读,主进程完成工作了,避免阻塞直到fork完成,这样当主进程或子进程需要修改内存时,才会触发缺页异常,其中内核的缺页异常处理函数中,会将主进程所用物理内存,复制一份到子进程,此时才算fork完成;

缺点

会数据丢失,因为通常是通过配置的方式触发生成RDB,是每隔n秒如果有m个key变更就会触发,那已有m-1个key变更,未达到持久化条件,此时宕机,就会丢失这段时间变更的key了。

AOF

不像RDB产生快照,它是client的每个写操作命令,以追加的形式写入到磁盘的AOF文件,在redis重启时会重新执行AOF文件中的写命令即可将数据恢复到内存中;

其中AOF,它是有三种写入策略的,可以通过在redis.conf配置:

重写机制

不像RDB的二进制小文件,因为每个写命令都会追加AOF文件,那体积会越来越大,例如不断set key a,set key b,set key c,这些对同一个key的不断赋值,可以使用重写机制,只写入最新的value为c即可,很好的节省文件大小。

而且重写机制为避免影响正常的执行命令,也不是只用到主线程的,说说重写过程:

①首先创建一个子进程,负责AOF的重写操作;

②根据当前reids的内存数据的值,目前redis对于key的最新值就是c了,写入新的AOF文件,如list中有所有元素,也是用RPUSH命令将所有元素写入,而不是写入该list逐个添加元素的记录;

③在重写的过程中,还是会继续接收client的操作请求,为了避免数据不一致,主进程会将这些新的写命令同时写入一个缓冲区(aof_rewrite_buf)中;

④在重写机制完成后,会将aof_rewrite_buf缓冲区的写命令继续添加到新的AOF文件中;

⑤将新的AOF文件替换掉旧的AOF文件;

触发方式
手动触发

使用BGREWRITEAOF触发AOF重写;

自动触发

通过配置文件中的参数控制自动触发条件,要配置下面这两个参数:

auto-aof-rewrite-min-size:AOF文件达到该大小时允许重写,默认是64M;

auto-aof-rewrite-percentage:当前AOF文件大小相对于上次重写后的增长百分比达到该值出发重写;

MP-AOF

上面的重写机制,是存在严重的内存开销,因为在重写过程中,除了写原来的aof缓冲区,然后再到aof旧文件,还写入了一份重复的aof_rewrite_buf内存开销,而且还会损耗cpu的开销。

MP-AOF机制,它是将AOF原来的一份文件,改成三个文件,如下,第一个"ll"命令查看的是重写前的三个文件,第二个"ll"查看的是重写后的三个文件

一开始base.aof文件是为0,正常执行client的写命令,会追加到incr.aof文件,触发重写后,将incr.aof文件的内容重写,也就是只获取最新的key值,往base.aof文件写,可以看到aof.1.base.aof变成aof.2.base.aof文件了,然后incr.aof也从2开始了,避免在重写过程中,写多了一份在aof_rewrite_buf缓冲区,大大节省内存和cpu损耗。

RDB和AOF混合模式

即利用了RDB加载快的优点,还利用了AOF保存命令完整性的优点;

相关推荐
C_V_Better4 分钟前
Spring Security 如何防止 CSRF 攻击?
java·开发语言·数据结构·后端·算法·spring·csrf
customer081 小时前
【开源免费】基于SpringBoot+Vue.JS酒店管理系统(JAVA毕业设计)
java·vue.js·spring boot·后端·spring cloud·开源
充满诗意的联盟1 小时前
DDD该怎么去落地实现(4)多对多关系
java·开发语言
快乐非自愿1 小时前
Java中使用FFmpeg拉取RTSP流
java·开发语言·ffmpeg
Code额1 小时前
SpringBoot 中的 Redis 序列化
spring boot·redis
天天向上杰1 小时前
地基简识Spring MVC 组件
java·spring·mvc·springmvc
武昌库里写JAVA1 小时前
【Redis学习】Redis Docker安装,自定义config文件(包括RDB\AOF setup)以及与Spring Boot项目集成
java·开发语言·spring boot·学习·课程设计
MinggeQingchun2 小时前
Python - Python操作Redis
数据库·redis·缓存
是一只派大鑫2 小时前
从头开始学SpringMVC—02获取请求参数&向域对象共享数据
java·后端·springmvc
大丈夫在世当日食一鲲2 小时前
1JVM概念
java