【缓存策略】你知道 Cache Aside(缓存旁路)这个缓存策略吗

👉博主介绍: 博主从事应用安全和大数据领域,有8年研发经验,5年面试官经验,Java技术专家,WEB架构师,阿里云专家博主,华为云云享专家,51CTO 专家博主

⛪️ 个人社区:个人社区
💞 个人主页:个人主页
🙉 专栏地址: ✅ Java 中级
🙉八股文专题:剑指大厂,手撕 Java 八股文

在这里插入图片描述

文章目录

      • 1. 缓存策略 Cache Aside 是什么?
      • 2. 缓存策略 Cache Aside 的应用场景
      • 3. 缓存策略 Cache Aside 的优缺点
      • 4. 用 Java 模拟使用 Cache Aside 策略
        • 1. 引入依赖
        • 2. 配置 Redis
        • 3. 创建缓存服务
        • 4. 创建用户服务
        • 5. 创建控制器
        • 6. 启动类

1. 缓存策略 Cache Aside 是什么?

Cache Aside(缓存旁路) 是一种常见的缓存策略,其核心思想是在读取数据时,先从缓存中读取,如果缓存中没有数据,则从数据库中读取,并将数据写入缓存;在写入数据时,直接更新数据库,并从缓存中移除该数据。

具体步骤:

  1. 读取数据

    • 尝试从缓存中读取数据。
    • 如果缓存中存在数据,直接返回。
    • 如果缓存中不存在数据,从数据库中读取数据。
    • 将从数据库中读取的数据写入缓存,然后返回数据。
  2. 写入数据

    • 直接更新数据库。
    • 从缓存中移除该数据,以避免缓存中的数据与数据库中的数据不一致。

2. 缓存策略 Cache Aside 的应用场景

Cache Aside 适用于以下场景:

  1. 读多写少:适用于读取操作远多于写入操作的场景,如新闻网站的文章阅读。
  2. 数据更新不频繁:适用于数据更新不频繁,但读取非常频繁的场景。
  3. 数据一致性要求不高:适用于对数据一致性要求不高的场景,可以容忍短暂的数据不一致。
  4. 高并发读取:适用于高并发读取的场景,可以显著减轻数据库的负载。

3. 缓存策略 Cache Aside 的优缺点

优点:

  1. 性能提升:通过缓存减少对数据库的访问次数,提高读取性能。
  2. 减轻数据库压力:减少数据库的读取请求,减轻数据库的负载。
  3. 灵活性:可以在不修改业务逻辑的情况下,通过缓存策略提升系统性能。

缺点:

  1. 数据不一致:在写入数据后,缓存中的数据可能已经过期,导致短暂的数据不一致。
  2. 缓存击穿:如果大量请求同时访问同一个缓存键,而该键在缓存中不存在,会导致大量请求直接打到数据库,造成数据库压力。
  3. 缓存雪崩:如果缓存中的数据在同一时间过期,大量请求会同时打到数据库,造成数据库压力。

4. 用 Java 模拟使用 Cache Aside 策略

下面是一个简单的 Java 示例,模拟使用 Cache Aside 策略。

1. 引入依赖

pom.xml 中添加 Redis 依赖(假设使用 Redis 作为缓存):

<dependencies>
    <!-- Spring Boot Starter Data Redis -->
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-data-redis</artifactId>
    </dependency>

    <!-- Spring Boot Starter Web -->
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-web</artifactId>
    </dependency>

    <!-- Spring Boot Starter Test -->
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-test</artifactId>
        <scope>test</scope>
    </dependency>
</dependencies>
2. 配置 Redis

application.properties 中配置 Redis:

spring.redis.host=localhost
spring.redis.port=6379
3. 创建缓存服务

创建一个服务类来实现 Cache Aside 策略:

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;

@Service
public class CacheService {

    @Autowired
    private RedisTemplate<String, String> redisTemplate;

    @Autowired
    private UserService userService;

    public String getUserById(String userId) {
        // 尝试从缓存中读取数据
        String cachedUser = redisTemplate.opsForValue().get(userId);
        if (cachedUser != null) {
            return cachedUser;
        }

        // 如果缓存中没有数据,从数据库中读取
        String user = userService.getUserById(userId);
        if (user != null) {
            // 将数据写入缓存
            redisTemplate.opsForValue().set(userId, user);
        }

        return user;
    }

    public void updateUser(String userId, String userName) {
        // 直接更新数据库
        userService.updateUser(userId, userName);

        // 从缓存中移除该数据
        redisTemplate.delete(userId);
    }
}
4. 创建用户服务

创建一个简单的用户服务类,模拟数据库操作:

import org.springframework.stereotype.Service;

@Service
public class UserService {

    public String getUserById(String userId) {
        // 模拟从数据库中读取用户数据
        // 实际应用中,这里应该是数据库查询操作
        return "User: " + userId;
    }

    public void updateUser(String userId, String userName) {
        // 模拟更新数据库中的用户数据
        // 实际应用中,这里应该是数据库更新操作
        System.out.println("Updating user: " + userId + " to " + userName);
    }
}
5. 创建控制器

创建一个控制器类,提供 RESTful API 接口:

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;

@RestController
public class UserController {

    @Autowired
    private CacheService cacheService;

    @GetMapping("/user")
    public String getUser(@RequestParam String id) {
        return cacheService.getUserById(id);
    }

    @PostMapping("/user")
    public String updateUser(@RequestParam String id, @RequestParam String name) {
        cacheService.updateUser(id, name);
        return "User updated: " + id + " to " + name;
    }
}
6. 启动类

创建一个启动类来启动 Spring Boot 应用:

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;

@SpringBootApplication
public class CacheAsideApplication {

    public static void main(String[] args) {
        SpringApplication.run(CacheAsideApplication.class, args);
    }
}

运行项目

  1. 启动 Redis 服务器

    • 确保 Redis 服务器正在运行,可以通过命令 redis-server 启动。
  2. 启动 Spring Boot 应用

    • 运行 CacheAsideApplication 类的 main 方法,启动 Spring Boot 应用。
  3. 测试接口

    • 使用 Postman 或浏览器测试接口:
      • GET http://localhost:8080/user?id=1:读取用户数据。
      • POST http://localhost:8080/user?id=1&name=JohnDoe:更新用户数据。

精彩专栏推荐订阅:在下方专栏👇🏻
✅ 2023年华为OD机试真题(A卷&B卷)+ 面试指导
✅ 精选100套 Java 项目案例
✅ 面试需要避开的坑(活动)
✅ 你找不到的核心代码
✅ 带你手撕 Spring
✅ Java 初阶

在这里插入图片描述

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

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

相关文章

2024版最新kali linux 新手教程(非常详细)零基础入门到精通,收藏这篇就够了

您是否有兴趣使用 Kali Linux&#xff0c;但不知道从哪里开始&#xff1f;您来对地方了。 Kali Linux 是一个强大的渗透测试和道德黑客工具&#xff0c;提供许多工具和资源。 本 Kali Linux 教程将向您展示如何下载和安装它、解释桌面并强调您应该知道的关键领域。接下来&…

Android JNI 技术入门指南

引言 在Android开发中&#xff0c;Java是一种主要的编程语言&#xff0c;然而&#xff0c;对于一些性能要求较高的场景&#xff08;如音视频处理、图像处理、计算密集型任务等&#xff09;&#xff0c;我们可能需要使用到C或C等语言来编写底层的高效代码。为了实现Java代码与C…

国标GB28181视频平台EasyCVR私有化部署视频平台对接监控录像机NVR时,录像机“资源不足”是什么原因?

EasyCVR视频融合云平台&#xff0c;是TSINGSEE青犀视频“云边端”架构体系中的“云平台”系列之一&#xff0c;是一款针对大中型项目设计的跨区域、网络化、视频监控综合管理系统平台&#xff0c;通过接入视频监控设备及视频平台&#xff0c;实现视频数据的集中汇聚、融合管理、…

HarmonyOS NEXT:模块化项目 ——修改应用图标+启动页等

涉及官方文档 应用配置文件应用/组件级配置图标资源规范 涉及到app.json5配置文件和module.json5配置文件 1、 icon和label的校验。 IDE从5.0.3.800版本开始&#xff0c;不再对module.json5中的icon和label做强制校验&#xff0c;因此module.json5与app.json5只需要选择其一…

产品经理晋级-Axure中继器+动态面板制作美观表格

步骤如下&#xff1a; 将你的表格&#xff08;制作好的表格复制&#xff09; 在工作页面中&#xff0c;添加动态面板&#xff0c;并把刚才复制的表格添加进来

java 面向对象高级

1.final关键字 class Demo{public static void main(String[] args) {final int[] anew int[]{1,2,3};// anew int[]{4,5,6}; 报错a[0]5;//可以&#xff0c;解释了final修饰引用性变量&#xff0c;变量存储的地址不能被改变&#xff0c;但地址所指向的对象的内容可以改变} }什…

计算机网络:运输层 —— 运输层端口号

文章目录 运输层端口号的分类端口号与应用程序的关联应用举例发送方的复用和接收方的分用 运输层端口号的分类 端口号只具有本地意义&#xff0c;即端口号只是为了标识本计算机网络协议栈应用层中的各应用进程。在因特网中不同计算机中的相同端口号是没有关系的&#xff0c;即…

echarts引入自定义字体不起作用问题记录

echarts引入自定义字体不起作用问题记录 1、问题描述 初始化界面字体不作用&#xff0c;当界面更新后字体样式正常显示 2、原因描述 这通常是由于字体文件加载延迟导致的。ECharts 在初始化时可能还没有加载完字体文件&#xff0c;因此无法正确应用字体样式 3、解决方案 …

AscendC从入门到精通系列(一)初步感知AscendC

1 什么是AscendC Ascend C是CANN针对算子开发场景推出的编程语言&#xff0c;原生支持C和C标准规范&#xff0c;兼具开发效率和运行性能。基于Ascend C编写的算子程序&#xff0c;通过编译器编译和运行时调度&#xff0c;运行在昇腾AI处理器上。使用Ascend C&#xff0c;开发者…

JavaScript——函数、事件与BOM对象

一、系统函数(JS中预置的函数) JS的预置函数在遇到非数字字符时会停止解析 parseInt 转整型 parseFloat 转浮点型 isNaN !isNaN("10") 检测是否纯数字 eval 把字符串转成算式并计算 1.parseInt(string, radix); 语法&#xff1a; string&#x…

Python学习从0到1 day28 Python 高阶技巧 ⑤ 多线程

若事与愿违&#xff0c;请相信&#xff0c;上天自有安排&#xff0c;允许一切如其所是 —— 24.11.12 一、进程、线程 现代操作系统比如Mac OS X&#xff0c;UNIX&#xff0c;Linux&#xff0c;Windows等&#xff0c;都是支持“多任务”的操作系统。 进程 进程&#xff1a;就…

OpenCV视觉分析之目标跟踪(11)计算两个图像之间的最佳变换矩阵函数findTransformECC的使用

操作系统&#xff1a;ubuntu22.04 OpenCV版本&#xff1a;OpenCV4.9 IDE:Visual Studio Code 编程语言&#xff1a;C11 算法描述 根据 ECC 标准 78找到两幅图像之间的几何变换&#xff08;warp&#xff09;。 该函数根据 ECC 标准 ([78]) 估计最优变换&#xff08;warpMatri…

彻底解决单片机BootLoader升级程序失败问题

文章目录 1、引言2、MicroBoot&#xff1a;优雅的解决升级问题问题1&#xff1a;bootloader 在跳转到app前没有清理干净存在的痕迹问题2&#xff1a; 需要 APP 传递信息给 Bootloader问题3&#xff1a; APP单独运行没有问题&#xff0c;通过Bootloader跳转到APP运行莫名死机问题…

v-html 富文本中图片使用element-ui image-viewer组件实现预览,并且阻止滚动条

效果 导入组件 import ElImageViewer from "element-ui/packages/image/src/image-viewer"; components:{ ElImageViewer },模板使用组件 <el-image-viewerv-if"isShowPics":on-close"closeViewer":url-list"srcList"/>定义两…

山寨一个Catch2的SECTION

Catch2 是一个 C 单元测试库&#xff0c;吹嘘自己比 NUnit 和 xUnit 还要高明&#xff0c; 支持在 TEST_CASE() 中的多个 SECTION&#xff0c; 意思是说 SECTION 外头的代码相当于setup 和 teardown&#xff0c;section 内部则被认为是实际的 test case&#xff0c; 这种写法可…

深入剖析【C++继承】:单一继承与多重继承的策略与实践,解锁代码复用和多态的编程精髓,迈向高级C++编程之旅

​​​​​​​ &#x1f31f;个人主页&#xff1a;落叶 &#x1f31f;当前专栏: C专栏 目录 继承的概念及定义 继承的概念 继承定义 定义格式 继承基类成员访问⽅式的变化 继承类模板 基类和派⽣类间的转换 继承中的作⽤域 隐藏规则 成员函数的隐藏 考察继承【作⽤…

36.Redis核心设计原理

本文针对前面的讲解做一次总结 1.Redis基本特性 1.非关系型的键值对数据库&#xff0c;可以根据键以O(1)的时间复杂度取出或插入关联值 2.Redis的数据是存在内存中的 3.键值对中键的类型可以是字符串&#xff0c;整型&#xff0c;浮点型等&#xff0c;且键是唯一的 4.键值对中…

项目模块十七:HttpServer模块

一、项目模块设计思路 目的&#xff1a;实现HTTP服务器搭建 思想&#xff1a;设计请求路由表&#xff0c;记录请求方法与对应业务的处理函数映射关系。用户实现请求方法和处理函数添加到路由表&#xff0c;服务器只接受请求并调用用户的处理函数即可。 处理流程&#xff1a; …

vue项目npm run serve出现【- Network: unavailable】(从排查到放弃)

1. 问题现象 环境&#xff1a; 系统&#xff1a;win11node&#xff1a;v16.20.2“vue”: “2.6.10” 执行npm run serve启动vue项目&#xff0c;期望&#xff1a; App running at:- Local: http://localhost:9528/ - Network: http://x.x.x.x:9528/实际&#xff1a; App runn…

喜报|超维机器人荣获昇腾AI创新大赛铜奖

近日&#xff0c;在备受瞩目的昇腾AI创新大赛中&#xff0c;超维机器人凭借扎实的技术实力和创新产品&#xff0c;荣获大赛铜奖。这一荣誉不仅展现了超维机器人在智能巡检领域的技术创新与突破&#xff0c;也标志着超维机器人的智能巡检解决方案在人工智能领域获得了广泛认可&a…