Redis设计与实现-数据持久化

embedded/2025/3/16 14:40:18/

数据持久化

  • 1、RDB持久化
    • 1.1 RDB文件的创建和载入
    • 1.2 自动间隔保存
    • 1.3 RDB文件结构
  • 2、AOF持久化
    • 2.1 AOF写入
    • 2.2 AOF载入
    • 2.3 AOF重写

如有侵权,请联系~
如有错误,也欢迎批评指正~
本篇文章大部分是来自学习《Redis设计与实现》的笔记

1、RDB持久化

RDB持久化功能所生成的RDB文件是一个经过压缩的文件,通过RDB文件可以还原数据。

1.1 RDB文件的创建和载入

生成RDB文件有两个命令:

  • save命令:阻塞Redis服务器进程,直到RDB文件创建完成之前不能处理任何其他命令
  • bgsave命令:创建一个子进程,由子进程负责RDB文件的创建,redis父进程正常处理其他命令

这两种方式底层都是调用rdbSave函数。

针对于RDB的载入,没有明确的命令。而是服务器在启动的时候就会自动检测RDB文件,自动载入。RDB文件的载入是通过rdbLoad函数完成,在载入的过程正,服务器一直是处于阻塞状态。

redis正在执行bgsave命令的时候,不会阻塞服务器执行其他命令。但是不包含save、bgsave、bgrewriteaof命令。当redis正在执行bgsave命令的时候,如果服务端又收到了:

  • save命令:save命令会被拒绝,父子进程都会调用rdbsave方法,防止产生竞争
  • bgsave命令:bgsave命令也会被拒绝,也会同时调用rdbsave方法
  • bgrewriteaof命令:bgrewriteaof命令会被延迟到bgsave命令执行完执行。如果redis正在执行bgrewriteaof命令,收到bgsave命令会被服务器拒绝。bgrewriteaof和bgsave命令不能同时执行是因为创建两个子进程,存在大量的磁盘读写,影响性能。

1.2 自动间隔保存

除了使用命令保存RDB文件,配置文件中也会有相关的配置。默认配置:

save 900 1      # 900 秒内至少有 1 个键被修改时触发快照
save 300 10     # 300 秒内至少有 10 个键被修改时触发快照
save 60 10000   # 60 秒内至少有 10000 个键被修改时触发快照

只要满足一个条件就会触发bgsave进行自动保存。上述配置对应于redisServer结构体中的:

struct redisServer {...struct saveparam *saveparams;  // 动态数组,存储所有 save 配置项// 修改计数器 long long dirty;//上一次执行保存的时间time_t lastsave;...
};
struct saveparam {time_t seconds;  // 时间间隔(秒)int changes;     // 键修改次数
};

saveparam数组用来存储上述自动间隔保存RDB的配置数据。
dirty记录自从上次save或者bgsave命令之后服务器【所有数据库】进行修改的次数,lastsave记录上次save或者bgsave命令成功执行的时间。

这个是由serverCron函数【默认100ms执行一次】进行扫描,通过saveparam和dirty、lastsave一起来判断是否需要触发bgsave进行RDB保存。(serverCron函数不止是进行判断是不是需要进行持久化,还包括判断过期键)

1.3 RDB文件结构

在这里插入图片描述
当服务器读取到db_number之后,就会切换到相应的数据库。db_number会根据数据库号的大小占用不同的大小。
每个键值对的结构如下,如果这个键没有设置过期时间,则没有前两个字段:
在这里插入图片描述
在RDB文件存储数据的时候,只会存储真实的数据,不会存储redisObject这种元数据。

2、AOF持久化

与RDB持久化【将键值对数据保存到RDB文件】不同,AOF持久化是将写入命令按照请求协议格式resp保存到AOF文件中。

2.1 AOF写入

数据每次写入都会存储到aof_buf缓存中。

struct redisServer {...// 持久化相关char *rdb_filename;        // RDB 文件路径int aof_state;             // AOF 状态sds aof_buf;               // AOF 缓冲区,存储到这里....
}

服务端进程其实就是一个事件loop循环, 这个循环中包含:文件事件【执行请求并返回数据】、时间事件【如定时任务serverCron函数】。
在结束一个事件之前,都会调用flushAppendOnlyFile函数【决定是不是将aof缓存中的数据写入、同步到AOF文件中】。伪代码如下:
在这里插入图片描述
flushAppendOnlyFile同步的时机取决于服务器中appendfsync配置:always、everysec、no等配置。
这三种策略只是区分数据同步fsync到磁盘的时机,而写入命令是每次执行完都会将命令写入到aof_buf中和操作系统的缓存中,不区分上述配置。

2.2 AOF载入

服务器启动之后,会创建伪客户端【不带有网络连接的redis客户端】,因为redis命令需要在客户端的上下文中执行,并且载入的命令是来自于AOF文件,而不是网络连接,所以创建一个不带有网络连接的伪客户端。
然后从AOF文件中一条一条命令读取出来,伪客户端进行执行。
在这里插入图片描述

2.3 AOF重写

随着程序不断的运行,AOF文件会越来越大,占用磁盘空间并且当服务器重启进行数据加载的时候,AOF文件的载入也会需要很长时间。所以AOF重写就很有必要。
AOF重写其实就是将某一时刻的所有数据库的所有数据dump按照redis命令进行输出。例如

rpush list "A" "B"
rpush list "C"
rpush list "D" "E" "F"
lpop list
rpop list
rpush list "G" "H"
// 如果此刻进行AOF重写,就会将上述执行的结果汇总为一条执行语句【不严谨,如果数据量太大可能分为多条语句,受这个参数影响REDIS.AOF_REWRITE_ITENS_PER_CM 】
// 重写AOF文件之后,AOF文件中只会记录这一条数据rpush list "B" "C" "D" "E" "G" "H" 而不是上述六条执行语句

AOF文件在重写的时候,会挨个遍历所有数据库,遍历每个数据库的每个键值对,并且还会过滤掉过期的键。

AOF重写是在子进程中执行的,并且使用了写时复制。在进行AOF重写期间,redis在进行执行写入命令的时候,除了执行命令、将命令写入到AOF缓冲区之外,还需要写入到AOF重写缓冲区中。
等AOF重写将所有数据库中的数据写完之后,子进程会给父进程一个信号,然后父进程:

  • 将AOF重写缓冲区中的命令写入到刚刚新的重写的AOF文件中,保证数据的一致性。
  • 原子性的将新的重写的AOF文件替换为原AOF文件。

http://www.ppmy.cn/embedded/173081.html

相关文章

呵护斜颈老人:解锁护理关键,重塑健康生活

痉挛性斜颈是一种以颈肌扭转或阵挛导致头部倾斜、旋转为特征的疾病,给老人的生活带来诸多不便。做好健康护理,对缓解症状、提升生活质量至关重要。 在日常生活中,要注重老人的姿势管理。为老人选择高度合适、有良好颈部支撑的枕头&#xff0c…

基于SpringBoot + Vue 的校园论坛系统

系统环境:Windows 推荐运行环境:jdk8/17/23mavenMySQLnode14.0 服务端技术:SpringbootMybatis 前端技术:VueaxiosElement-UI 用户功能模块: 登录注册:用户可以创建账户并登录系统。 浏览帖子:用…

【Go】字符串相关知识点

字符串(String)是 Go 语言中最常用的数据类型之一,广泛应用于文本处理、数据解析、网络通信等场景。Go 语言的字符串是不可变的 UTF-8 字节序列,在性能和安全性方面与其他编程语言有所不同。 源代码 package main//字符类型 byt…

【大模型(LLMs)RAG 检索增强生成 面经】

1 RAG 基础面 1.1 为什么大模型需要外挂 (向量) 知识库? 如何将外部知识注入大模型,最直接的方法:利用外部知识对大模型进行微调。 思路: 构建几十万量级的数据,然后利用这些数据 对大模型进行微调,以将 额外知识注入大模型 优点: 简单粗暴 缺点: 这几十万量级的数据…

机器学习之线性代数

文章目录 一、引言:线性代数为何是AI的基石二、向量:AI世界的基本构建块(一)向量的定义(二)向量基础操作(三)重要概念 三、矩阵:AI数据的强大容器(一&#xf…

大模型训练全流程深度解析

前些天发现了一个巨牛的人工智能学习网站,通俗易懂,风趣幽默,忍不住分享一下给大家。点击跳转到网站。https://www.captainbed.cn/north 文章目录 1. 大模型训练概览1.1 训练流程总览1.2 关键技术指标 2. 数据准备2.1 数据收集与清洗2.2 数据…

Xcode16 Archive Error - Command SwiftCompile failed with a nonzero exit code

1.打包错误信息 Command SwiftCompile failed with a nonzero exit code 2.找到原因 It’s because in Xcode 16, UITextField, they add a new function with the same name onReturn. It’s ok when you compile and run, but will return error DeadArgSignatureOpt when…

探索Maas平台与阿里 QWQ 技术:AI调参的魔法世界

摘要:本文介绍了蓝耘 Maas 平台在人工智能领域的表现及其核心优势,包括强大的模型支持、高效的资源调度和友好的操作界面。文章还探讨了蓝耘 Maas 平台与阿里 QWQ 技术的融合亮点及应用拓展实例,并提供了调参实战指南,最后对蓝耘 …