深入了解架构中常见的4种缓存模式及其实现

news2025/1/8 6:40:56

4种缓存模式

随着应用程序的复杂性日益增加,缓存管理变得至关重要。缓存不仅能有效减轻数据库负载,还能显著提升数据访问速度。选择合适的缓存模式能够在不同的业务场景下发挥出最佳效果。

本文将详细介绍四种常见的缓存模式:Cache-Aside (旁路缓存)Read-Through (透读缓存)Write-Through (透写缓存) 和 Write-Back / Write-Behind (写后缓存),并通过代码示例深入剖析它们的实现。

1.Cache-Aside (旁路缓存)

概述

Cache-Aside(旁路缓存)模式,又叫 Lazy-Loading(懒加载)模式,在这种模式下,缓存的读取和写入由应用程序直接管理。应用程序首先尝试从缓存中读取数据,若缓存未命中,则从数据库中加载数据并将其存储在缓存中;对于更新操作,应用程序直接更新数据库,并更新或删除缓存中的相关数据。

在这里插入图片描述

工作流程:

  • 读取数据:
    1. 应用程序查询缓存。
    2. 如果缓存命中,返回缓存数据。
    3. 如果缓存未命中,应用程序从数据库加载数据,并将其存入缓存。
  • 更新数据:
    1. 应用程序直接更新数据库。
    2. 然后,应用程序更新或删除缓存中的数据。

优缺点:

优点:

  • 灵活:开发者可以根据需求选择从缓存或数据库读取数据。
  • 减少数据库负载,提高访问速度。
  • 简单易于实现,开发者可以完全控制缓存管理。

缺点:

  • 需要手动管理缓存,增加了开发和维护的复杂度。
  • 存在缓存一致性问题,需要小心处理缓存的清除和更新。

适用场景

适用于读取频繁但更新较少的数据。例如,用户信息、商品详情、广告推荐等。

代码示例

import java.util.HashMap;
import java.util.Map;

public class CacheAside {
    private Map<String, String> cache = new HashMap<>();
    private Map<String, String> database = new HashMap<>();

    public String getFromCacheOrDatabase(String key) {
        String data = cache.get(key);
        if (data == null) {
            data = database.get(key);
            cache.put(key, data);
        }
        return data;
    }
}

2. Read-Through (透读缓存)

概述

Read-Through 模式下,缓存层自动管理数据的读取。当应用程序请求数据时,缓存层会先检查缓存,如果缓存命中则直接返回数据;如果缓存未命中,则缓存层自动从数据库加载数据,并将数据存入缓存。
Read-Through

工作流程:

  1. 应用程序请求数据。
  2. 如果缓存中存在数据,直接返回数据。
  3. 如果缓存中没有数据,缓存系统会从数据库加载数据,并将数据存入缓存。

独立设计缓存层

  • 缓存层实现:需要一个独立的缓存系统(如 Redis、Memcached)。缓存系统需要能够在数据未命中时,自动从数据库加载数据,并缓存这些数据。
  • 缓存一致性:通常需要通过缓存管理器来控制数据过期、更新和一致性。

优缺点:

优点:

  • 简化了应用程序的逻辑,应用程序无需关心数据是从缓存还是数据库加载。
  • 减少了数据库的负担,提升了系统性能。

缺点:

  • 增加了对缓存层的依赖,缓存层需要具备高可用性和强大的扩展性。
  • 当缓存未命中时,可能会造成缓存层和数据库的负载增加。

适用场景

适用于需要快速访问并且能够容忍一定程度缓存一致性问题的应用场景,比如商品数据、用户会话等。

代码示例

import java.util.HashMap;
import java.util.Map;

public class ReadThrough {
    private Map<String, String> cache = new HashMap<>();
    private Map<String, String> database = new HashMap<>();

    public String getFromCacheOrReadThroughDatabase(String key) {
        String data = cache.get(key);
        if (data == null) {
            data = database.get(key);
            cache.put(key, data);
        }
        return data;
    }
}

Cache-Aside(旁路缓存)和Read-Through(透读缓存)的区别

Cache-Aside (旁路缓存)

数据访问方式:

  • 在Cache-Aside模式中,应用程序首先查询缓存,如果缓存中不存在所需数据,则从数据库中获取数据,并将数据存储到缓存中。应用程序负责直接操作缓存。
    缓存更新策略:
  • 数据更新时,应用程序负责更新缓存。这意味着数据的写入和更新操作会首先更新数据库,然后再更新缓存。缓存中的数据通常在需要时才会被更新。
Read-Through (透读缓存)

数据访问方式:

  • 在Read-Through模式中,应用程序直接查询缓存,如果缓存中不存在所需数据,则缓存系统会负责从数据库中获取数据,并将数据存储到缓存中。应用程序并不直接操作缓存。
    缓存更新策略:
  • 数据更新时,缓存系统会负责更新缓存。当数据发生变化时,缓存系统会自动更新缓存,确保缓存中的数据与数据库中的数据保持一致。
区别总结
  • Cache-Aside模式中,应用程序负责读取和写入缓存,而Read-Through模式中,缓存系统负责从数据库中读取数据并更新缓存。
  • 在Cache-Aside中,数据更新时需要应用程序负责更新缓存,而在Read-Through中,缓存系统会自动更新缓存以保持数据一致性。
  • Cache-Aside适用于读取频率高、写入频率低的场景,而Read-Through适用于需要保证数据一致性的场景。

3. Write-Through (透写缓存)

概述

Write-Through 模式要求数据在写入时同时更新缓存和数据库。当应用程序写入数据时,数据首先写入缓存,然后立即写入数据库。这种模式保证了缓存中的数据始终与数据库中的数据一致

Write-Through

工作流程:

  1. 应用程序写入数据。
  2. 数据首先写入缓存。
  3. 然后,数据被同步写入数据库。

独立设计缓存层:

  • 缓存层实现:需要一个缓存层,在写数据时同步更新缓存和数据库。这样可以确保缓存中的数据与数据库中的数据保持一致。

优缺点:

优点:

  • 保证了缓存和数据库中的数据一致性。
  • 每次数据更新时,都会更新缓存,避免了缓存过期问题。

缺点:

  • 写操作会增加缓存层和数据库的负担,可能影响性能。
  • 相对于其他模式,写入操作的延迟较高。

适用场景

适用于数据一致性要求较高的场景,如库存管理、金融交易等。

代码示例

import java.util.HashMap;
import java.util.Map;

public class WriteThrough {
    private Map<String, String> cache = new HashMap<>();
    private Map<String, String> database = new HashMap<>();

    public void writeToCacheAndDatabase(String key, String value) {
        cache.put(key, value);
        database.put(key, value);
    }
}

4. Write-Back / Write-Behind (写后缓存)

概述

Write-Back(写后缓存)模式下,应用程序先将数据写入缓存,而不立即写入数据库。数据在缓存中更新后,定期或按需将更新后的数据异步写入数据库。这种模式的好处是减少了写操作的延迟,提高了性能,但需要处理数据同步的问题。

在这里插入图片描述

工作流程:

  1. 应用程序将数据写入缓存。
  2. 数据更新首先写入缓存,而不直接写入数据库。
  3. 缓存会定期或异步地将数据写入数据库。

独立设计缓存层:

  • 缓存层实现:需要一个独立的缓存层,该层不仅处理数据读取,还负责缓存数据的写入。为了确保数据最终一致性,通常会使用异步操作将缓存中的数据写回数据库。

优缺点:

优点:

  • 提高了写操作的性能,减少了对数据库的写入压力。
  • 写操作的延迟较低,因为数据只写入缓存。

缺点:

  • 需要处理缓存与数据库的数据同步问题,确保最终一致性。
  • 如果缓存数据未及时写入数据库,可能导致数据丢失。

适用场景

适用于不需要即时写入数据库的场景,例如日志收集、批量数据更新等。

代码示例

import java.util.HashMap;
import java.util.Map;

public class WriteBack {
    private Map<String, String> cache = new HashMap<>();
    private Map<String, String> database = new HashMap<>();
    private Map<String, Boolean> dirtyMap = new HashMap<>();

    public void writeToCache(String key, String value) {
        cache.put(key, value);
        dirtyMap.put(key, true);
    }

    public void writeToDatabase(String key) {
        if (dirtyMap.getOrDefault(key, false)) {
            String data = cache.get(key);
            database.put(key, data);
            dirtyMap.put(key, false);
        }
    }
}

Read-Through(透读缓存)与 Write-Through(透写缓存)和 Write-Back(写后缓存)相比的优势和劣势

Read-Through(透读缓存)的优势:
  • 数据一致性:Read-Through模式可以确保缓存中的数据与数据库中的数据保持一致。
  • 简化应用逻辑:应用程序无需关心缓存的更新,缓存系统负责从数据库中读取数据并更新缓存,简化了应用的逻辑。
  • 减少数据库负载:通过缓存数据,可以减少对数据库的频繁访问,降低数据库负载,提高系统性能。
Read-Through(透读缓存)的劣势:
  • 读取延迟:如果数据不在缓存中,需要从数据库中获取数据并更新缓存,可能会增加读取数据的延迟。
  • 频繁读取场景下不够高效:对于频繁读取的数据,如果每次都要从数据库中获取数据,可能会降低系统性能。
  • 数据更新时的一致性延迟:数据更新后,缓存中的数据需要等到下一次读取时才会被更新,可能导致一段时间内的数据不一致。
总结:

Read-Through适合对数据一致性要求较高的场景,但可能存在读取延迟和频繁读取效率不高的问题。在选择缓存模式时,应根据具体业务需求和系统特点来权衡各种因素,选择最适合的缓存模式。

其他

下面介绍一下其他变种策略,感兴趣可以自己去搜索,这里不再详细介绍。

Write Around

Write Around策略是一种变体的写入策略,当数据被更新时,仅更新底层数据存储,而不更新缓存,缓存的数据只有在被读取时才会更新

Refresh-ahead

Refresh-ahead 是一种缓存预取策略,旨在提高系统的响应速度,尤其是在可预测的访问场景下,与其他缓存策略的被动性不同,refresh-ahead通过主动预测未来可能会被访问的数据,提前从主存储载入缓存中,从而减少未来请求时的缓存未命中率(Cache Miss)。


总结

除了 Cache-Aside (旁路缓存) 模式外,其他三种模式(Read-Through (透读缓存)Write-Through (透写缓存)Write-Back / Write-Behind (写后缓存))通常需要独立设计缓存层,或者通过专门的服务来封装缓存的读写操作。具体来说,这三种模式都需要一个完整的封装机制来处理数据的访问和缓存的一致性问题。

缓存策略是优化系统性能的重要工具,不同的缓存模式适用于不同的场景。理解这些模式的工作原理、优缺点和适用场景有助于在开发中选择最合适的缓存策略。

  • Cache-Aside:由应用程序自己管理缓存,提供灵活性,适合复杂业务逻辑。
  • Read-Through:在缓存缺失时从主存取数据并更新缓存,适合读多写少场景。
  • Write-Through:实时在缓存和主存同步写数据,保证一致性但写入稍慢。
  • Write-Back:先写缓存,后续批量写入主存,提升写性能,但最终一致性难以保证。选择应根据性能需求和一致性要求平衡。

选择合适的缓存模式,能够在提高性能的同时,确保系统的稳定性和数据一致性

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

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

【论文阅读】处理器芯片敏捷设计方法:问题与挑战

作者&#xff1a;包云岗老师 包云岗老师是计算机体系结构方向的大牛&#xff0c;推动了体系结构方面的开源事业! 欢迎对本栏目感兴趣的人学习"一生一芯"~ 学习体会&#xff1a; 已有的软硬件生态系统和开发成本制约了对新结构的探索。但目前仍在几种路线上做尝试~ 1…

Android记单词app(包含数据库)

一、功能与要求 实现功能:设计与开发记单词系统的,系统功能包括用户登录、用户注册、单词操作(单词的添加、查询、修改及删除)以及忘记密码等。 指标要求:通过用户登录、用户注册、单词操作、忘记密等功能的设计与开发,掌握Android常用布局、控件的使用、监听器的设置以及…

数据结构与算法学习笔记----树与图的深度优先遍历

数据结构与算法学习笔记----树与图的深度优先遍历 author: 明月清了个风 first publish time: 2024.12.9 pa⭐️这里只有一道题哈哈。 Acwing 846.树的重心 给定一棵树&#xff0c;树中包含 n n n个节点&#xff08;编号 1 ∼ n 1 \sim n 1∼n&#xff09;和 n − 1 n - 1 n…

TSWIKI知识库软件

TSWIKI 知识库软件介绍 推荐一个适合本地化部署、自托管的知识库软件 TSWIKI介绍 tswiki 是一个适合小团队、个人的知识库、资料管理的软件&#xff0c;所有数据均本地化存储。可以本地化、私有云部署&#xff0c;安装简单。在线预览。 主要功能说明 1、简化的软件依赖和安…

mid360使用cartorapher进行3d建图导航

1. 添加urdf配置文件&#xff1a; 添加IMU配置关节点和laser关节点 <!-- imu livox --> <joint name"livox_frame_joint" type"fixed"> <parent link"base_link" /> <child link"livox_frame" /> <o…

第四十六篇 Vision Transformer论文翻译

论文连接:https://arxiv.org/abs/2010.11929 GitHub:https://github.com/google-research/vision_transformer 摘要 虽然Transformer架构已成为自然语言处理任务的实际标准,但其在计算机视觉中的应用仍然有限。在计算机视觉中,注意力机制要么与卷积网络结合使用,要么在保…

【VUE2】纯前端播放海康视频录像回放,视频格式为rtsp格式,插件使用海康视频插件

一、需求 1、后端从海康平台拉流视频回放数据&#xff0c;前端进行页面渲染播放&#xff0c;视频格式为rtsp eg&#xff1a; 基本格式&#xff1a;rtsp://<username>:<password><ip_addr>:<port>/<path>参数说明&#xff1a; username&#xff…

STL库中list的使用与迭代器的实现

STL库中list的使用与迭代器的实现 1.使用list中的部分函数assignspliceremoveuniquemeger 2.list的部分功能实现&#xff08;重点&#xff09;框架迭代器的实现 1.使用list中的部分函数 assign 功能一&#xff1a;当前链表的节点全部销毁&#xff0c;替换成迭代区间的值 功能二…

2024年华中杯数学建模C题基于光纤传感器的平面曲线重建算法建模解题全过程文档及程序

2024年华中杯数学建模 C题 基于光纤传感器的平面曲线重建算法建模 原题再现 光纤传感技术是伴随着光纤及光通信技术发展起来的一种新型传感器技术。它是以光波为传感信号、光纤为传输载体来感知外界环境中的信号&#xff0c;其基本原理是当外界环境参数发生变化时&#xff0c…

ETCD的封装和测试

etcd是存储键值数据的服务器 客户端通过长连接watch实时更新数据 场景&#xff1a; 当主机A给服务器存储 name&#xff1a; 小王 主机B从服务器中查name ,得到name-小王 当主机A更改name 小李 服务器实时通知主机B name 已经被更改成小李了。 应用&#xff1a;服务注册与发…

Cesium 问题: 添加billboard后移动或缩放地球,标记点位置会左右偏移

文章目录 问题分析原先的:添加属性——解决漂移移动问题产生新的问题:所选的经纬度坐标和应放置的位置有偏差解决坐标位置偏差的问题完整代码问题 添加 billboard 后, 分析 原先的: // 图标加载 function addStation ({lon, lat, el, testName

进入 Dystopia:第九周游戏指南

本指南将为大家详细说明在第八周的每个体验中可以获得的奖励。 在杂草丛生的反乌托邦废墟中生存&#xff0c;随着大自然重新开垦这片土地&#xff0c;文明已陷入绝望。穿越高耸入云、摇摇欲坠的摩天大楼&#xff0c;抵御末世社会的各种危险。适应这个文明与荒野之间的界限已经消…

leetcode 面试经典 150 题:验证回文串

链接验证回文串题序号125类型字符串解题方法双指针法难度简单 题目 如果在将所有大写字符转换为小写字符、并移除所有非字母数字字符之后&#xff0c;短语正着读和反着读都一样。则可以认为该短语是一个 回文串 。 字母和数字都属于字母数字字符。 给你一个字符串 s&#xf…

Android 屏幕采集并编码为H.264

前言 我们前面基于摄像机的图像采集以及编解码已经完成了&#xff0c;那么接下来计划后面的三篇博文分别实现Android屏幕采集实现并进行H.264编解码、MIC音频采集并编码为AAC以及AAC解码播放&#xff0c;希冀可以通过这六篇博文能够对Android上面的音视频编解码有一个初步的学…

深入探索 Compose 渲染流程:从 UI 树到 Skia 绘制的实现解析

文章目录 前言Compose 渲染流程概述1. Compose 解析1.1 Compose 声明性 UI1.2 Compose 编译1.2.1 Compose 编译概述1.2.2 代码示例1.2.3 编译过程细节 1.3 组合与重组合1.3.1 组合&#xff08;Composition&#xff09;1.3.2 重组合1.3.3 组合与重组合的区别1.3.4 组合与重组合的…

PySpark3.4.4_基于StreamingContext实现网络字节流统计分析

网络字节流与嵌套字节流的区别 概念解释 网络嵌套字节流&#xff1a; 在网络编程的情境下&#xff0c;网络嵌套字节流通常是指将字节流&#xff08;字节序列&#xff09;以一种分层或者包含的方式进行组织&#xff0c;用于在网络传输过程中更好地处理数据。例如&#xff0c;在一…

【Homework】【8】Learning resources for DQ Robotics in MATLAB

作业任务 创建一个名为“VS050RobotDH”的类&#xff0c;该类代表Denso VS050机器人&#xff0c;其DH参数如下表所示&#xff0c;并且完全由旋转关节组成。&#xff08;请记住第6课的内容&#xff09; θ \theta θ d d d a a a α \alpha α − π -\pi −π0.3450 π 2 \fra…

如何防御ARP欺骗 保护IP安全

在数字化浪潮席卷全球的今天&#xff0c;网络安全威胁如同暗流涌动&#xff0c;时刻考验着我们的防范能力。其中&#xff0c;ARP欺骗攻击作为一种隐蔽性强、成本低廉且危害严重的网络攻击手段&#xff0c;成为众多网络安全事件中的一颗“毒瘤”。那么我们究竟是如何防御ARP欺骗…

低代码场景案例配置——复杂数据模型下表单与表格关联字段的保存

主子表的场景是每个业务系统都绕不过的功能点&#xff0c;低代码能不能在业务上用的起来&#xff0c;这个是必须过的门槛。那么什么主子表有哪些场景的应用&#xff0c;如何配置呢&#xff0c;接下来我们就举个例详细说明 订单管理系统&#xff0c;场景描述&#xff1a; 在电…

方案拆解 | 打击矩阵新规频出!2025矩阵营销该怎么玩?

社媒平台的矩阵营销又要“变天”了&#xff1f;&#xff01; 11月18日&#xff0c;小红书官方发表了被安全薯 称为“小红书史上最严打击黑灰产专项”新规&#xff0c;其中就包括黑灰产矩阵号的公告。 ▲ 图源&#xff1a;小红书 实际上&#xff0c;不包括这次&#xff0c;今年…