多级缓存设计实践

缓存是什么?

缓存技术是一种用于加速数据访问的优化策略。它通过将频繁访问的数据存储在高速存储介质(如内存)中,减少对慢速存储设备(如硬盘或远程服务器)的访问次数,从而提升系统的响应速度和性能。

缓存的基本原理是:当某个数据被请求时,系统首先检查缓存中是否已存储该数据。如果缓存中存在,则直接返回缓存中的数据,称为“缓存命中”;如果缓存中没有该数据,则从源数据存储(如数据库或远程服务器)中获取数据,并将其存入缓存,以便下次请求时使用。

缓存的常见类型:

  1. 内存缓存:将数据存储在内存中,常见的缓存系统有 Redis 和 Memcached。内存的访问速度远远高于硬盘,因此可以大幅提升性能。

  2. 磁盘缓存:将数据存储在硬盘或 SSD 中,相比内存访问较慢,但可以存储更大量的数据。适用于需要较大存储空间但对速度要求不如内存严格的场景。

  3. 浏览器缓存:网页浏览器会缓存静态资源(如图片、JavaScript 文件等)以减少重复请求,从而提高用户体验和加载速度。

  4. CDN缓存:内容分发网络(CDN)将静态内容缓存到靠近用户的边缘节点,以降低延迟,提高访问速度。

  5. 服务缓存:如Go的本地缓存
  6. MySQL缓存:change buffer 机制,查询缓存机制(已废弃)

性能比较:内存类大于磁盘类,客户端类大于服务端类,近的节点大于远的节点(存储介质&距离)

常见的缓存策略:

  1. LRU(Least Recently Used):当缓存空间不足时,优先淘汰最近最少使用的数据。(冷热数据)

  2. FIFO(First In, First Out):先进先出,最早加入缓存的数据会被优先移除。(新旧数据)

  3. TTL(Time To Live):每个缓存数据都有一个有效期,到期后会被自动清除或重新加载。(定时器机制)

  4. Write-through:每次对缓存进行修改时,同时将数据写入原始数据存储。(双写,保证数据一致性)

  5. Lazy Loading(懒加载):仅当需要时才加载数据到缓存中。(节省资源)

  6. Cache Invalidation(缓存失效):当数据源发生变化时,缓存中的数据需要被标记为无效或更新,以保持数据的一致性。(驱动更新)

示例:

Redis 提供了多种淘汰策略来处理内存达到上限时的情况。以下是 Redis 常见的淘汰策略:

  1. noeviction
    当内存不足时,Redis 不会淘汰任何数据,并且会返回错误。适用于不允许丢失数据的场景。

  2. allkeys-lru
    基于最少最近使用(LRU,Least Recently Used)算法来淘汰最不常用的键。当 Redis 达到内存限制时,会从所有的键中淘汰最少使用的键。

  3. volatile-lru
    只对设置了过期时间的键进行 LRU 淘汰。如果内存不足,Redis 会选择最久未使用的、设置了过期时间的键来删除。

  4. allkeys-random
    随机删除键,适用于在内存不足时,删除任意一个键。

  5. volatile-random
    随机删除设置了过期时间的键。它只删除有过期时间的键,不会影响没有过期时间的键。

  6. volatile-ttl
    根据过期时间(TTL,Time To Live)来淘汰键,选择即将过期的键进行删除。这种策略适用于缓存场景,删除那些快过期的键。

常见的缓存问题:

1. 缓存穿透

缓存穿透是指客户端请求的数据既不在缓存中,也不在数据库中,导致每次请求都直接访问数据库,绕过了缓存。

解决方案

  • 空缓存策略:对于不存在的数据,可以将其在缓存中设置一个空值(如 null 或特殊标记),并设置一个较短的过期时间。这样下次请求相同数据时,可以直接返回空缓存,避免每次都去数据库查询。
  • 缓存过滤:在请求数据前,进行数据验证和过滤(如验证用户输入),确保请求的数据是有效的,减少无效请求。

2. 缓存雪崩

缓存雪崩指的是缓存中的大量数据在同一时间过期,导致大量请求同时访问数据库,造成数据库压力剧增,甚至崩溃。

解决方案

  • 随机过期时间:设置缓存的过期时间时,加上随机偏差,避免多个缓存项在同一时刻过期。
  • 分布式缓存:将缓存分布到多个服务器上,避免单个缓存服务器故障导致整个缓存系统崩溃。
  • 提前加载缓存:根据访问量和数据的热点情况,提前将关键数据加载到缓存中,避免全量加载导致的瞬时压力。

3. 缓存击穿

缓存击穿是指缓存中某个热点数据过期或被删除后,有大量请求同时访问该数据,导致直接访问数据库,从而引发数据库压力过大。

解决方案

  • 加锁或队列机制:在缓存失效时,对该数据加锁或使用队列来保证同一时间只有一个请求去数据库查询并更新缓存,其他请求等待查询结果。
  • 缓存预热:可以在缓存失效前,提前加载或更新缓存,避免缓存失效后直接访问数据库。

4. 缓存一致性问题

缓存与数据库之间的数据可能会出现不一致的情况。例如,数据在数据库中更新了,但缓存没有及时更新,导致用户看到的数据是过期的。

解决方案

  • 缓存失效策略:在数据更新后,立即删除缓存中相应的条目。可以通过应用程序逻辑主动更新缓存,或者设置合适的过期时间。
  • 双写一致性:在对数据库进行修改时,同时修改缓存中的数据,确保缓存和数据库的数据一致性。
  • 延迟一致性:如果严格一致性要求不高,可以允许一定时间内缓存与数据库不一致,稍后通过后台任务同步缓存。

5. 缓存污染

缓存污染是指缓存中存入了错误、无效或不再使用的数据,这些数据会导致缓存效率下降,甚至对应用性能造成影响。

解决方案

  • 数据校验:在将数据写入缓存之前,进行有效性检查,确保缓存的数据是正确的。
  • 定期清理:定期扫描和清理缓存中的无效或过期数据,保持缓存的健康状态。
  • 合理设置缓存过期时间:缓存过期时间应根据数据的变化频率来合理设置,避免缓存存储过多过期或不常用的数据。

6. 缓存并发问题

当多个请求同时访问缓存中的同一数据时,可能会导致缓存更新的冲突,尤其是在高并发场景下,可能会造成缓存不一致或资源竞争。

解决方案

  • 使用锁机制:可以为缓存数据增加锁(如互斥锁),保证同一时间只有一个请求可以更新缓存,避免并发更新冲突。
  • 异步更新:通过异步方式更新缓存,避免长时间的同步阻塞。

7. 缓存击穿和过期

数据缓存的生命周期管理是一个复杂的问题,如果没有合理的策略,缓存中的数据可能在一段时间后过期,导致大量请求直接访问数据库。

解决方案

  • 永不过期的缓存:对于一些不容易发生变化的数据,可以设置为永不过期,避免频繁更新缓存。
  • 使用合适的缓存策略:比如定期刷新缓存、主动更新缓存等,确保缓存始终保持有效。

8. 内存溢出

当缓存数据过多,超出了缓存系统的内存限制时,可能会导致缓存系统发生内存溢出,影响系统的稳定性。

解决方案

  • 限制缓存大小:根据应用的实际需求,设置合适的缓存大小限制,避免缓存过多的数据。
  • LRU(最少最近使用)淘汰策略:对于不常使用的数据,可以采用 LRU 或其他淘汰策略来清理缓存,避免内存溢出。

9. 缓存穿透/渗透与数据泄露

在一些恶意攻击或错误请求的情况下,缓存可能会泄露敏感数据,特别是在没有加密或限制访问控制的情况下。

解决方案

  • 数据加密:对于缓存中的敏感数据进行加密存储,防止数据泄露。
  • 访问控制:根据不同用户权限设置缓存访问策略,防止不合法请求访问敏感数据。

10. 缓存更新延迟

在某些情况下,缓存更新的延迟可能会导致系统反应迟缓,特别是在高并发环境中。

解决方案

  • 异步更新缓存:对于非实时性要求非常高的场景,可以通过异步任务更新缓存,避免阻塞主流程。
  • 批量更新缓存:在数据有大批量变化时,可以采用批量更新策略,而不是频繁更新单条缓存数据。

缓存的优点:

  • 提高性能:通过减少对慢速存储的访问,缓存可以显著加快数据的读取速度。
  • 减轻服务器负担:减少对数据库或其他后端系统的请求,降低它们的负载。
  • 节省带宽:通过缓存远程内容(如网站资源或API响应),减少带宽消耗。

缓存的挑战:

  • 一致性问题:缓存中的数据可能与原始数据不同步,导致数据不一致。通常需要通过策略(如缓存失效、刷新机制)来解决这一问题。
  • 内存占用:缓存使用内存或磁盘存储,会占用一定的资源,需要合理规划和管理。
  • 缓存穿透:恶意用户可能直接绕过缓存,频繁访问源数据,从而导致源系统的压力增加。

为什么要设计多级缓存?什么是CPU的多级缓存?

CPU 多级缓存(Multi-level Cache,简称 L1/L2/L3 Cache)是为了提高 CPU 访问内存的速度而设计的一种缓存层次结构。由于直接从主内存读取数据的速度相对较慢,因此,现代 CPU 采用了多级缓存来加速数据访问,减少访问内存的延迟。CPU 多级缓存通常包括以下几层:

1. L1 缓存(一级缓存)

  • 位置:L1 缓存在 CPU 核心内,距离处理器最接近。
  • 速度:L1 缓存是所有缓存层中速度最快的,通常在几纳秒(ns)级别。
  • 容量:L1 缓存的容量较小,一般在 16KB 到 128KB 之间。
  • 用途:L1 缓存通常分为两个部分:
    • L1 数据缓存:存储数据。
    • L1 指令缓存:存储即将执行的指令。
  • 特点:L1 缓存是最小的,但也最快,主要存储当前正在处理的数据和指令。由于其速度快,L1 缓存的命中率对整体性能影响较大。

2. L2 缓存(二级缓存)

  • 位置:L2 缓存位于 CPU 核心内或与多个核心共享(这取决于 CPU 架构)。
  • 速度:L2 缓存的速度比 L1 缓存稍慢,但仍比主内存快,通常在 10 纳秒左右。
  • 容量:L2 缓存的容量比 L1 大,通常在 128KB 到几 MB 之间。
  • 用途:L2 缓存用于存储从 L1 缓存中淘汰的数据,或者那些 L1 缓存没有命中的数据。它在 L1 缓存和 L3 缓存之间起到了桥梁作用,缓解了 CPU 核心访问主内存时的瓶颈。
  • 特点:L2 缓存要比 L1 大,速度稍慢,但通常每个核心都拥有独立的 L2 缓存。

3. L3 缓存(三级缓存)

  • 位置:L3 缓存通常是多个 CPU 核心共享的缓存层级,它位于 L2 缓存之上,甚至可能在多核处理器中共享给所有核心。
  • 速度:L3 缓存的速度比 L1 和 L2 缓存慢,但仍比访问主内存快,通常在几十纳秒(ns)级别。
  • 容量:L3 缓存的容量最大,一般从几 MB 到几十 MB 不等,具体取决于处理器架构。
  • 用途:L3 缓存用于存储那些在 L1 和 L2 缓存中都未命中的数据,它起到了对多个核心的共享存储作用,帮助缓解访问主内存的压力。
  • 特点:L3 缓存是多个核心共享的,容量大但速度较慢。其设计目的是减少多个 CPU 核心之间的访问冲突和数据不一致。

4. 主内存(RAM)

当缓存(L1、L2、L3)都没有命中时,CPU 会访问主内存(RAM)。虽然主内存的存取速度比缓存慢得多(通常在几十到几百纳秒之间),但它的容量较大,能够存储更多的数据。

5. 缓存命中率和访问延迟

  • 缓存命中率:缓存命中率指的是 CPU 请求的数据在缓存中找到的概率。缓存命中率越高,CPU 能更快地从缓存中获取数据,性能表现越好。
  • 访问延迟:访问延迟是指从 CPU 发出请求到数据返回的时间。L1 缓存的访问延迟最短,而主内存的访问延迟最长。

多级缓存的设计目的

  1. 提高性能:通过层级化缓存,尽量减少 CPU 访问较慢的主内存的次数,从而提高整体计算性能。
  2. 平衡速度和容量:L1 缓存速度最快,但容量小;L3 缓存容量大,但速度较慢。通过层级缓存的设计,可以在速度和容量之间找到平衡。
  3. 减少内存带宽压力:多个级别的缓存减少了 CPU 对主内存的访问,降低了内存带宽的压力,提高了 CPU 处理能力。

多级缓存的业务实现

L1 :客户端缓存(SDK实现-Redis/服务缓存)

L2 :  服务端缓存(本地缓存)

L3:  第三方缓存(Redis)

1、在管理功能进行埋点,持久化DB数据到Redis,保证数据一致性

  • 数据双写 ,先写Redis,再写数据库,数据库失败,则回滚缓存数据(单条记录要加锁)
  • 数据检测脚本,监控redis 数据和数据库的一致性,晚上跑,自动更新修复数据

2、服务缓存- Go使用本地缓存,作为临时缓存挡住一部分请求

  • 缓存时间设置为 1 min ,配置到 Apollo,主要挡住突发流量以及热点数据流量
  • 降级处理,本地缓存失效,走Redis获取,再存储到本地缓存

3、SDK 获取时,在当前服务写缓存,缓存时间5秒

好处:

1、多级缓存机制,保证服务高可用

坏处:

1、增加维护成本

2、数据实时性变差(要看业务能否接受)

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/927605.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

鸿蒙开发-HMS Kit能力集(地图服务、华为支付服务)

地图服务 Map Kit(地图服务)是鸿蒙生态下的一个地图服务,为开发者提供强大而便捷的地图能力,助力全球开发者实现个性化地图呈现、地图搜索和路线规划等功能,轻松完成地图构建工作。 Map Kit提供了千万级别的 Poi&…

【k8s深入学习之 event 记录】初步了解 k8s event 记录机制

event 事件记录初始化 一般在控制器都会有如下的初始化函数,初始化 event 记录器等参数 1. 创建 EventBroadcaster record.NewBroadcaster(): 创建事件广播器,用于记录和分发事件。StartLogging(klog.Infof): 将事件以日志的形式输出。StartRecording…

STM32 ADC --- 知识点总结

STM32 ADC — 知识点总结 文章目录 STM32 ADC --- 知识点总结cubeMX中配置注解单次转换模式、连续转换模式、扫描模式单通道采样的情况单次转换模式:连续转换模式: 多通道采样的情况禁止扫描模式(单次转换模式或连续转换模式)单次…

如何打开链接中的网址

文章目录 1 概念介绍2 使用方法3 示例代码我们在上一章回中介绍了包管理相关的内容,本章回中将介绍如何使用url_launcher包.闲话休提,让我们一起Talk Flutter吧。 1 概念介绍 我们在这里介绍url_launcher包主要用来打开Url中的内容,Url可以是电话号码,网址,邮箱等内容。如…

cpp的set

一、关联式容器和键值对 1.关联式容器 关联式容器也是用来存储数据的&#xff0c;与序列式容器不同的是&#xff0c;其里面存储的是<key, value>结构的键值对&#xff0c;在数据检索时比序列式容器效率更高 2.键值对 用来表示具有一一对应关系的一种结构&#xff0c;…

Vue3学习宝典

1.ref函数调用的方式生成响应式数据&#xff0c;可以传复杂和简单数据类型 <script setup> // reactive接收一个对象类型的数据 import { reactive } from vue;// ref用函数调用的方式生成响应式数据&#xff0c;可以传复杂和简单数据类型 import { ref } from vue // 简…

数据结构——排序第三幕(深究快排(非递归实现)、快排的优化、内省排序,排序总结)超详细!!!!

文章目录 前言一、非递归实现快排二、快排的优化版本三、内省排序四、排序算法复杂度以及稳定性的分析总结 前言 继上一篇博客基于递归的方式学习了快速排序和归并排序 今天我们来深究快速排序&#xff0c;使用栈的数据结构非递归实现快排&#xff0c;优化快排&#xff08;三路…

数字经济发展的新视角:数字产业化、数据资产化、产业数字化与数据产业

在当今数字化、网络化和智能化的时代&#xff0c;数字经济的快速发展催生了一系列新兴概念&#xff0c;其中“数字产业化、数据资产化、产业数字化与数据产业”尤为引人注目。这四个概念不仅代表了数字经济发展的不同阶段和方向&#xff0c;也深刻影响着传统产业的转型升级和经…

springboot370高校宣讲会管理系统(论文+源码)_kaic

毕 业 设 计&#xff08;论 文&#xff09; 高校宣讲会管理系统设计与实现 摘 要 传统办法管理信息首先需要花费的时间比较多&#xff0c;其次数据出错率比较高&#xff0c;而且对错误的数据进行更改也比较困难&#xff0c;最后&#xff0c;检索数据费事费力。因此&#xff0c…

ansible自动化运维(一)配置主机清单

目录 一、介绍 1.1了解自动化运维 1.2 ansible简介 1.3 ansible自动化运维的优势 1.4 ansible架构图 二、部署ansible 2.1 基本参数 2.2 Ansible帮助命令 2.3 配置主机清单 2.3.1 查看ansible的所有配置文件 2.3.2 /etc/ansible/ansible.cfg常用配置选项 2.3.3 ssh密…

计算机网络 —— HTTP 协议(详解)

前一篇文章&#xff1a;网页版五子棋—— WebSocket 协议_网页可以实现websocket吗-CSDN博客 目录 前言 一、HTTP 协议简介 二、HTTP 协议格式 1.抓包工具的使用 2.抓包工具的原理 3.抓包结果 4.HTTP协议格式总结 三、HTTP 请求 1. URL &#xff08;1&#xff09;UR…

GaussDB的BTree索引和UBTree索引

目录 一、简介 二、BTree索引和UBTree索引结构 三、BTree索引和UBTree索引优势 四、总结与展望 一、简介 数据库通常使用索引来提高业务查询的速度。本文将深入介绍GaussDB中最常用的两种索引&#xff1a;BTree索引和UBTree索引。我们将重点解读BTree索引和UBTree索引的存储…

通义灵码走进北京大学创新课堂丨阿里云云原生 10 月产品月报

云原生月度动态 云原生是企业数字创新的最短路径。 《阿里云云原生每月动态》&#xff0c;从趋势热点、产品新功能、服务客户、开源与开发者动态等方面&#xff0c;为企业提供数字化的路径与指南。 趋势热点 &#x1f947; 通义灵码走进北京大学创新课堂&#xff0c;与 400…

python 练习题

目录 1&#xff0c;输入三个整数&#xff0c;按升序输出 2&#xff0c;输入年份及1-12月份&#xff0c;判断月份属于大月&#xff0c;小月&#xff0c;闰月&#xff0c;平月&#xff0c;并输出本月天数 3&#xff0c;输入一个整数&#xff0c;显示其所有是素数因子 4&#…

IDEA 2024 配置Maven

Step 1:确定下载Apache Maven版本 在IDEA 2024中&#xff0c;随便新建一个Maven项目&#xff1b; 在File下拉菜单栏中&#xff0c;找到Setings&#xff1b; 在Build&#xff0c;Execution&#xff0c;Deployment中找到Maven 确定下载的Apache Maven版本应略低于或等于IDEA绑…

ubuntu20.04更换安装高版本CUDA以及多个CUDA版本管理

Ubuntu 20.04下多版本CUDA的安装与切换 CUDA安装配置环境变量软连接附上参考博客CUDA安装 cuda官方下载地址 因为我需要安装的是11.1版本的,所以这里按着11.1举例安装 安装命令如下: wget https://developer.download.nvidia.com/compute/cuda/11.1.0/local_installers/cu…

Web基础

实践目标 &#xff08;1&#xff09;Web前端HTML&#xff08;2&#xff09;Web前端javascipt&#xff08;3&#xff09;Web后端&#xff1a;MySQL基础&#xff1a;正常安装、启动MySQL&#xff0c;建库、创建用户、修改密码、建表&#xff08;4&#xff09;Web后端&#xff1a…

C++:unordered_map与unordered_set详解

文章目录 前言一、KeyOfT1. 为什么需要仿函数&#xff1f;2. MapKeyOfT与SetKeyOfT代码实现 二、迭代器1. 设计背景2. 为什么需要存储哈希表指针3. operator 的逻辑4. begin() 和 end() 的实现5. 友元和前置声明的作用6. 完整代码 三、迭代器map与set的复用1. map的复用&#x…

redis下载、基础数据类型、操作讲解说明,持久化、springboot整合等

1 Redis是什么 官网&#xff1a;https://redis.io 开发者&#xff1a;Antirez Redis诞生于2009年全称是Remote Dictionary Server 远程词典服务器&#xff0c;是一个基于内存的键值型NoSQL数据库。 Redis是一个开源的、高性能的键值对存储系统&#xff0c;它支持多种数据结构&…

《 C++ 修炼全景指南:二十五 》缓存系统的技术奥秘:LRU 原理、代码实现与未来趋势

摘要 本篇博客深入解析了 LRU&#xff08;Least Recently Used&#xff09;缓存机制&#xff0c;包括其核心原理、代码实现、优化策略和实际应用等方面。通过结合双向链表与哈希表&#xff0c;LRU 缓存实现了高效的数据插入、查找与删除操作。文章还对 LRU 的优化方案进行了详…