当前位置: 首页 > news >正文

【每日八股】复习 Redis Day2:Redis 的持久化(下)

文章目录

  • 昨日内容复习
    • 简述 Redis 持久化的两种策略
    • AOF 的三种持久化/写回策略?
    • AOF 的磁盘重写机制?
    • 为什么要先执行一个 Redis 命令,再将命令写入到 AOF 缓冲区?
    • AOF 重写的具体过程?
  • 复习 Redis Day2:Redis 的持久化(下)
    • AOF 子进程的内存跟主进程的内存数据不一致怎么办?
    • RDB 执行快照的时候,数据可以修改吗?
    • Redis 过期机制?
    • Redis 的内存淘汰策略?
    • Redis 持久化对过期键会如何处理?
    • Redis 主从模式中,对过期键如何处理?

昨日内容复习

简述 Redis 持久化的两种策略

AOF 和 RDB。

RDB
RDB(Redis Database)是整个 Redis 缓存的快照文件。Redis 会周期性地开启一个子进程来保存当前 Redis 缓存的快照,RDB 文件较小,适用于 Redis 备份和容灾恢复。

AOF
AOF(Append Only File)保存的是 Redis 的写命令,每当用户输入一条 Redis 指令,Redis 会先执行,再将这条指令追加到 AOF 缓冲区当中,根据同步策略,Redis 会将 AOF 缓冲区当中的指令追加到 AOF 文件当中。

混合持久化
定期生成 RDB 格式的数据快照作为基础,写入到 AOF 文件的头部。快照之后的写操作以 AOF 格式追加到同一文件当中。

混合持久化的优势是:

  • 快速回复:RDB 提供数据快速加载的能力;
  • 低数据丢失:AOF 记录增量操作,在启用 everysec 同步策略后最多丢失一秒的数据;
  • 兼容性:文件仍为 AOF 格式,兼容 Redis 工具链。

混合持久化的缺点:

  • 文件复杂度:混合文件的可读性较差;
  • AOF 重写开销:重写时需要生成 RDB 快照,在大型数据集的场景下,fork() 的开销较大,可能阻塞主进程。

AOF 的三种持久化/写回策略?

  • always:针对每一条 Redis 命令,执行后直接将它持久化到 AOF 文件中,这种做法的安全性最高,但是性能较差;
  • everysec:每一条 Redis 指令先写入 AOF 缓冲区,之后每秒持久化到 AOF 文件当中,最多丢失一秒的数据;
  • no:由操作系统择机将缓冲区中的指令持久化到 AOF 文件。

AOF 的磁盘重写机制?

AOF 的磁盘重写机制指的是随着 Redis 指令的增加,AOF 文件可能变得非常大,其中包含很多冗余、无效或重复的命令。Redis 重写的核心是基于当前 Redis 数据库的状态新建一个更紧凑的 AOF 文件,并以此替代旧的 AOF 文件。

具体来说,AOF Rewrite 触发后,「Redis 开启一个子进程」,将当前 Redis 缓存中的状态转为写命令写入到 AOF 文件当中。

为什么要先执行一个 Redis 命令,再将命令写入到 AOF 缓冲区?

先执行 Redis 命令可以保证写入到 AOF 缓冲区的每一条命令都是正确的,这样在通过 AOF 恢复 Redis 缓存时不需要花费额外的开销检查命令是否合法。

缺点在于如果 Redis 恰好在命令执行之后,保存到 AOF 之前宕机,那么这条记录会丢失。

AOF 重写的具体过程?

Redis 使用「子进程」进行重写,仅在子进程 fork() 时会短暂阻塞主进程。具体来说:

步骤一:主进程 fork 子进程
主进程 fork() 子进程,子进程获得 fork() 执行时数据状态的快照。

步骤二:子进程生成新的 AOF 文件
子进程遍历 Redis 缓存快照,将每个 key 的状态转为等效的 Redis 命令,写入临时文件。

步骤三:处理重写期间的增量数据
主进程继续处理客户端的请求,新的命令同时写入到旧的 AOF 缓冲区和重写 AOF 缓冲区/

步骤四:子进程完成重写
子进程生成新的 AOF 后,向主进程发送信号。主进程收到信号后,将重写缓冲区内的所有命令追加到新的 AOF 文件尾,并使用新的 AOF 替换旧的 AOF。

复习 Redis Day2:Redis 的持久化(下)

在这里插入图片描述

AOF 子进程的内存跟主进程的内存数据不一致怎么办?

在回答这个问题之前,先来学习一下什么是写时复制(Copy On Write,COW):写时复制的核心思想是,多个进程(或线程)共享同一份数据,只有在某个进程尝试修改数据时,才会真正复制该数据的新副本。这样可以减少不必要的内存复制,提高性能。

现在我们来回答这个问题。

AOF 重写开始时,主进程会 fork() 一个子进程,该子进程与主进程共享 fork() 时刻的内存页。AOF 重写开启后,主进程仍会继续处理请求,如果主进程接收到的新请求导致内存页被修改,此时会触发写时复制,主进程复制一个新的内存页并修改其中的数据,而子进程看到的仍然是微修改的内存页。

在 AOF 重写的过程中,Redis 设置了一个 AOF 重写缓冲区,客户端新追加的命令会同时写入旧的 AOF 缓冲区和重写缓冲区当中。子进程执行完重写之后,会读取缓冲区当中的重写命令并追加到新的 AOF 文件尾,确保数据的一致性。

根据答案,我个人认为上述回答更贴切的问题是,AOF 重写过程中如果有新的写命令追加,Redis 会如何处理。

RDB 执行快照的时候,数据可以修改吗?

可以,仍然基于写时复制技术完成快照的读取。

具体来说,Redis 主进程 fork() 一个子进程读取 fork() 执行时的数据快照,此时主进程和子进程共享内存页,主进程此时仍然可以处理新追加的客户端指令,如果客户端发出的是写命令,那么主进程触发写时复制,复制一个该命令对应内存的页并对其进行修改,此时子进程看到的仍然是 fork() 时的内存页。

Redis 过期机制?

Redis 允许为键(Key)设置生存时间(TTL),到期后自动删除。通过「过期字典 + 定期删除 + 惰性删除」的组合策略来实现。

惰性删除

  • 触发时机:当客户端尝试访问某个键时,Redis 会检查这个键是否过期,如果过期则直接删除并返回 nil,否则返回正常数据。
  • 优点:CPU 友好,只处理实际访问的键;
  • 缺点:如果键长期不被访问,即使过期也会长期占用内存(产生内存泄露的风险)。

定期删除

  • 触发时机:Redis 每隔一段时间随机抽取部分过期键检查并删除。默认每次检查 20 个键,如果发现超过 25% 的键过期,则继续抽取下一批,直到过期键的占比低于 25% 或超时。
  • 优点:降低内存泄漏风险。
  • 缺点:可能无法完全删除所有的键。

Redis 的内存淘汰策略?

当 Redis 内存到达限制时,会根据指定的淘汰策略自动删除键,以释放内存空间。

不进行数据淘汰
当 Redis 内存超限后,不淘汰任何数据,此时有新的数据写入的话则直接返回 OOM。

在设置了过期时间的数据中进行淘汰

  • volatile-random:随机淘汰设置了过期时间的任意键值;
  • volatile-ttl:优先淘汰更早过期的键值;
  • voaltile-lru:淘汰所有设置了过期时间的键值中最久未使用的键值;
  • volatile-lfu:淘汰所有设置了过期时间的键值中最少使用的键值;

在所有数据范围内进行淘汰

  • allkeys-random:随机淘汰任意键值;
  • allkeys-lru:淘汰整个键值中最久未使用的键值;
  • allkeys-lfu:淘汰整个键值中最少使用的键值。

Redis 持久化对过期键会如何处理?

RDB

  • 生成 RDB 快照时:过期的键不会写入到 RDB 文件中。
  • 加载 RDB 文件时:如果 Redis 以主节点模式启动,会检查过期键的时间,并在加载后立即删除过期的键。如果是从节点模式启动,过期键也会保留。从节点当中的过期键依赖主节点通过同步 DEL 命令删除。

AOF

  • AOF 文件记录:写入 AOF 的过期键以 DEL 命令形式记录。
  • AOF 重写时:子进程生成新的 AOF 时会跳过所有过期键。如果键在重写期间过期,主进程会追加 DEL 到缓冲区,确保最终的一致性。

Redis 主从模式中,对过期键如何处理?

从库不会进行过期扫描,即使从库中的 key 过期了,如果有客户端访问从库,依然可以得到 value 的值。从库的过期键处理依赖主节点的控制,主节点中 key 到期后,会在 AOF 文件中追加 DEL 命令,并同步到所有从节点,从库执行 DEL 命令来删除过期的 key。

相关文章:

  • 共建安全可控大模型AI底座,助力国产化升级——麒麟信安与新智惠想达成战略合作
  • STM32---串口通信USART
  • MySQL通用性能优化模板(MySQL General Performance Optimization Template)
  • Kafka简介
  • Maven 依赖坐标与BOM统一管理
  • ERR_SSL_KEY_USAGE_INCOMPATIBLE
  • Ubuntu18.04 升级最新版本Cmake
  • kaggle网站使用教程
  • 2025.04.23华为机考第三题-300分
  • JVM 生产环境问题定位与解决实战(七):实战篇——OSSClient泄漏引发的FullGC风暴
  • 网络原理————HTTP
  • ReAct Agent 实战:基于DeepSeek从0到1实现大模型Agent的探索模式
  • 【每天一个知识点】如何解决大模型幻觉(hallucination)问题?
  • Keras
  • Java与C语言核心差异:从指针到内存管理的全面剖析
  • 用 Firebase 和 WebRTC 快速搭建一款浏览器视频聊天应用
  • 线段树讲解(小进阶)
  • 基于UDP协议的群聊服务器开发(C/C++)
  • 深度解析算法之模拟
  • 第十五届蓝桥杯 2024 C/C++组 合法密码
  • 南京84.57亿元成交8宗宅地:仅秦淮区一宗地块溢价成交
  • 金光耀:被激活的复旦记忆
  • 网培机构围猎中老年人:低价引流卖高价课、“名师”无资质,舆论呼吁加强监管
  • 花3000元就能买“国际机构”的证书?揭秘假证产业链
  • 言短意长|把水搅浑的京东和美团
  • 大国重器飞天背后,有一位上海航天的“老法师”