百度360必应搜狗淘宝本站头条
当前位置:网站首页 > 技术教程 > 正文

Redis系列(三):缓存过期该如何剔除?RDB和AOF又是什么?

mhr18 2024-10-24 11:11 37 浏览 0 评论

一枚用心坚持写原创的“无趣”程序猿,在自身受益的同时也让朋友们在技术上有所提升。


前言

相信很多朋友和我一样,平时工作中经常用到 Redis 的过期特性,还有通过 RDB 和 AOF 文件恢复数据,但是它们是如何工作的,本文就来介绍一下;通过了解底层实现原理,从而更好的整体把控系统的正常运行。

目录

  • Redis 的缓存过期策略
  • RDB 的实现原理
  • AOF 的实现原理

Redis 的缓存过期策略

常见的缓存过期策略大概有如下几种:

  1. 定时剔除策略
  2. 定期剔除策略
  3. 惰性剔除策略

定时剔除策略

定时剔除是指在 Redis 后台启动一些定时任务,每隔一段时间会触发定时任务,然后由定时任务去扫描设置了过期时间的 key,一旦发现过期就会立即从内存中剔除。其执行流程大概如下所示:



  • dict:用于存储 Redis 数据库中所有的 key,所以可以理解成 Redis 是由一个大字典组成的。
  • expires:用于存储所有设置了过期时间的 key。

从图中可以看出,每次定时任务执行的时候,都会遍历 expires 中的所有 key 并判断 key 是否已经过期,若过期则将其从 expires 中剔除,同时将其从 dict 中的 key-value 也删除。

从流程图中可以看出,如果在同一时间过期的 key 特别多时,此时 CPU 一直忙于清理过期的 key,从而造成 Redis 服务的卡顿;但是使用此种清除策略可以做到尽早的过期的 key 从内存中剔除,而不会造成过期 key 遗留在内存。

定期剔除策略

定期剔除与定时剔除不同的是,每隔一段时间会执行一次检查操作,而每次检查时间最长为 25ms(假设每次执行周期为 25ms),在 25ms 内,每次采用贪心算法随机从 expires 中挑选一些 key 查看是否已经过期,如果已过期则从 Redis 中删除。

此种策略的好处是不会长时间占用 CPU,但是一些过期的 key 不会立马被删除,但随着时间点的推移,所有设置了过期时间的 key 都会被遍历一遍,最终还是可以被剔除掉。

惰性剔除策略

惰性剔除是指 key 到了过期时间,但还是"赖在"缓存中不被剔除,只有 key 发生读写操作的时候,才会检查当前 key 是否已经过期,如果过期了则将 key 从缓存中剔除,反之则对 key 进行正常的读写操作。基本操作流程如下:



关于惰性剔除策略的几点思考

  • 从流程图可以看出,key 过期后并不会立即被剔除,而只有 key 被使用时才会检测是否应该被剔除,此种方式剔除的好处是降低了 CPU 的压力。
  • 惰性剔除既然是只有 key 在被使用时才会剔除,那么如果某些 key 一直不被用到的话,那么就会在内存中常驻,从而在一定程度上浪费了内存。

对了了以上三种过期 key 的清理策略后,最终 Redis 采用了定期剔除和惰性剔除两种策略相结合的方式对过期的 key 进行剔除操作。一方面可以避免 CPU 的长时间占用导致卡顿的问题,另外一方面可以防止过期 key 长时间无法剔除的问题。

RDB 的实现原理



各部分组成说明

  • REDIS:常量,表示 RDB 文件的开头。
  • db_version:表示 RDB 文件的版本号。
  • EOF:表示 RDB 文件解析结束的位置表示。
  • check_num:校验和,通过前四部分计算得出的一个数值,当 RDB 文件被解析完成后得到的值与此值相比较,以此来判断解析 RDB 文件是否正常。
  • data_bases:表示数据库,用于存储实际数据的,data_bases 实际是由多个数据库组成,比如 0 号库和 2 号库里面都有数据,那么它表示两个库的数据。
  • TYPE:表示 value 的类型,比如字符串类型,List 类型,Set 类型等等。
  • key:表示 key 的内容,其一直是字符串类型。
  • value:表示值的内容,通过 Type 指定的类型,选择相应的解析方式来解析 value 中的值。
  • SELECTDB:表示开始选择数据库的标识。
  • db_number:表示当前数据要被恢复到那个数据库中,比如 db_number 为 2 时,则执行 select 命令,将库切到 2 号库中,然后将后续的数据写入到 2 号中。
  • key_values:表示存储的键值对

通过上述简要分析后可以大概了解到 RDB 文件是怎么构成的,通过相应的标识判断接下来的部分内容应该使用何种解析方式来解析。接下来我们来看看常见的几种类型的 value 组成结构长什么样子。

String 在 RDB 文件中的结构



左侧为普通的不带压缩的 value 在 RDB 文件中的展现形式,右侧为带压缩的 value 在 RDB 文件中的展现形式。

List 在 RDB 文件中的结构



  • list_length:表示 list 中的元素个数。
  • value_length:表示接下来的 value 的长度是多少。
  • value:表示实际存储的 value 的内容是什么。

关于 SET、ZSET 和 HASH 等在 RDB 文件中的存储结构和 List 基本上大同小异,所以在这里就不在展开了,感兴趣的朋友自行百度研究下。

AOF 的实现原理

AOF(Append Only File)是以写命令追加写入文件的方式来记录 Redis 中存储的数据,当 Redis 重启时,通过解析 AOF 文件即可将数据重新写入内存中。

AOF 文件写入流程



关于流程图的几点说明

  • 只有写命令才会被追加到 AOF 文件中。
  • 写命令是否同步追加到 AOF 文件中是由 appendfync 参数决定的,而 appendfync 可以配置三种情况,分别如下:
  • appendfync=always:表示每条写命令在被写入缓存 buffer 后,同时由该线程将命令追加写入到 AOF 文件中,此种做法最多只会有一条命令丢失的风险,但是由于由同一条线程进行操作,会导致该线程工作内容过多,从而使得处理写操作 QPS 相对比较低。
  • appendfync=everysce:表示写操作只需要将写命令写入缓存中,该工作线程的任务就算完成了,然后子线程会每隔一秒将缓存中的命令追加到 AOF 文件中,此种做法在一定程度上提高了写入的 QPS,但同时可能会丢失 1 秒内的写命令。
  • appendfync=no:表示写操作线程只需要将写命令写入缓存中,至于缓存中的写命令是什么时候被追加到 AOF 文件中,完全取决于操作系统,这种做法会使得写命令丢失的概率大大增加。
  • 写命令不断的被追加到 AOF 文件中,当写入速度增加时,势必会导致 AOF 快速变大,有可能会导致磁盘空间被大大占用,同时也增加了 AOF 文件恢复数据的时间,Redis 官方通过使用子进程的方式重写 AOF 文件,使得 AOF 文件减小。具体流程如下:


重写数据不一致的问题

如果子进程正在重写 AOF 文件的时候,有新的写命令进来的时候,则势必会造成通过 AOF 文件恢复的数据与当前 Redis 数据库中的数据不一致的问题。举个例子。

  1. 进程从数据库中读取 'key1' 对应的值为 'value1'。
  2. 在子进程准备将 set 'key1' 'value1' 命令追加到 AOF 文件中时,此时来了一条写命令 set 'key1' 'value2',将 'key1'对应的值修改成了 'vlaue2',但 AOF 文件中实际追加的命令对应的值为 'value1'。这就造成了数据不一致的问题。

那么该怎么解决呢?看下图:



在数据写入的时候,同时将写命令在重写缓冲区中写人一份,然后在重写 AOF 文件的时候,将 Redis 中读取的数据和重写缓冲区的数据进行合并之后,然后在写入到重写的 AOF 文件中。

总结

本篇文章讲解了 Redis 过期 key 的剔除策略,其采用了定期剔除和惰性剔除两种相结合的方式剔除过期 key;然后讲解了 RDB 文件内容的存储格式,通过了解数据的存储方式,可以更加清晰地理解 RDB 文件的数据恢复方式;最后讲解了 AOF 文件的实现原理,从而更加清晰地理解通过 AOF 文件如何进行数据恢复操作。

下篇文章我们来讲讲生产环境中集群是怎么工作的,敬请期待。

相关推荐

【推荐】一个开源免费、AI 驱动的智能数据管理系统,支持多数据库

如果您对源码&技术感兴趣,请点赞+收藏+转发+关注,大家的支持是我分享最大的动力!!!.前言在当今数据驱动的时代,高效、智能地管理数据已成为企业和个人不可或缺的能力。为了满足这一需求,我们推出了这款开...

Pure Storage推出统一数据管理云平台及新闪存阵列

PureStorage公司今日推出企业数据云(EnterpriseDataCloud),称其为组织在混合环境中存储、管理和使用数据方式的全面架构升级。该公司表示,EDC使组织能够在本地、云端和混...

对Java学习的10条建议(对java课程的建议)

不少Java的初学者一开始都是信心满满准备迎接挑战,但是经过一段时间的学习之后,多少都会碰到各种挫败,以下北风网就总结一些对于初学者非常有用的建议,希望能够给他们解决现实中的问题。Java编程的准备:...

SQLShift 重大更新:Oracle→PostgreSQL 存储过程转换功能上线!

官网:https://sqlshift.cn/6月,SQLShift迎来重大版本更新!作为国内首个支持Oracle->OceanBase存储过程智能转换的工具,SQLShift在过去一...

JDK21有没有什么稳定、简单又强势的特性?

佳未阿里云开发者2025年03月05日08:30浙江阿里妹导读这篇文章主要介绍了Java虚拟线程的发展及其在AJDK中的实现和优化。阅前声明:本文介绍的内容基于AJDK21.0.5[1]以及以上...

「松勤软件测试」网站总出现404 bug?总结8个原因,不信解决不了

在进行网站测试的时候,有没有碰到过网站崩溃,打不开,出现404错误等各种现象,如果你碰到了,那么恭喜你,你的网站出问题了,是什么原因导致网站出问题呢,根据松勤软件测试的总结如下:01数据库中的表空间不...

Java面试题及答案最全总结(2025版)

大家好,我是Java面试陪考员最近很多小伙伴在忙着找工作,给大家整理了一份非常全面的Java面试题及答案。涉及的内容非常全面,包含:Spring、MySQL、JVM、Redis、Linux、Sprin...

数据库日常运维工作内容(数据库日常运维 工作内容)

#数据库日常运维工作包括哪些内容?#数据库日常运维工作是一个涵盖多个层面的综合性任务,以下是详细的分类和内容说明:一、数据库运维核心工作监控与告警性能监控:实时监控CPU、内存、I/O、连接数、锁等待...

分布式之系统底层原理(上)(底层分布式技术)

作者:allanpan,腾讯IEG高级后台工程师导言分布式事务是分布式系统必不可少的组成部分,基本上只要实现一个分布式系统就逃不开对分布式事务的支持。本文从分布式事务这个概念切入,尝试对分布式事务...

oracle 死锁了怎么办?kill 进程 直接上干货

1、查看死锁是否存在selectusername,lockwait,status,machine,programfromv$sessionwheresidin(selectsession...

SpringBoot 各种分页查询方式详解(全网最全)

一、分页查询基础概念与原理1.1什么是分页查询分页查询是指将大量数据分割成多个小块(页)进行展示的技术,它是现代Web应用中必不可少的功能。想象一下你去图书馆找书,如果所有书都堆在一张桌子上,你很难...

《战场兄弟》全事件攻略 一般事件合同事件红装及隐藏职业攻略

《战场兄弟》全事件攻略,一般事件合同事件红装及隐藏职业攻略。《战场兄弟》事件奖励,事件条件。《战场兄弟》是OverhypeStudios制作发行的一款由xcom和桌游为灵感来源,以中世纪、低魔奇幻为...

LoadRunner(loadrunner录制不到脚本)

一、核心组件与工作流程LoadRunner性能测试工具-并发测试-正版软件下载-使用教程-价格-官方代理商的架构围绕三大核心组件构建,形成完整测试闭环:VirtualUserGenerator(...

Redis数据类型介绍(redis 数据类型)

介绍Redis支持五种数据类型:String(字符串),Hash(哈希),List(列表),Set(集合)及Zset(sortedset:有序集合)。1、字符串类型概述1.1、数据类型Redis支持...

RMAN备份监控及优化总结(rman备份原理)

今天主要介绍一下如何对RMAN备份监控及优化,这里就不讲rman备份的一些原理了,仅供参考。一、监控RMAN备份1、确定备份源与备份设备的最大速度从磁盘读的速度和磁带写的带度、备份的速度不可能超出这两...

取消回复欢迎 发表评论: