17:缓存机制-Java Spring

目录

  • 17.1 为什么需要缓存
  • 17.2 Redis 简介
  • 17.3 不同类型的缓存技术对比
  • 17.4 缓存机制在Java Spring框架中的应用
  • 17.5 应用场景
  • 17.6 注意事项

17.1 为什么需要缓存

1. 提升性能

缓存的核心价值在于将数据临时存储在快速访问的介质(如内存)中,减少对较慢存储(如硬盘或远程数据库)的直接访问。 这样一来,对于频繁访问的数据,应用程序可以直接从缓存获取,避免了昂贵的I/O操作和网络延迟,显著提升了响应速度。

2. 减轻数据库压力

大量并发请求往往会对数据库造成巨大压力,尤其是当涉及复杂的查询或数据更新时。 通过缓存热点数据,可以将大部分读操作转移到内存中处理,极大地减轻了数据库负担,有助于保持其稳定运行和高效处理核心事务。

3. 提高系统可用性

在某些故障场景下,如数据库短暂不可用或网络中断,缓存可以作为临时数据源,提供服务降级的能力,维持系统的部分功能运转。 此外,缓存还可以通过预加载、异步更新等方式,提前准备好可能需要的数据,确保在高负载情况下仍能提供快速响应。

17.2 Redis 简介

Redis 是一款开源、基于内存且支持多种数据结构的键值存储系统,广泛应用于缓存、消息队列、排行榜、会话存储等场景。

1. 数据类型丰富

Redis 支持丰富的数据结构,包括但不限于:

  • String(字符串):适用于存储简单的键值对,如用户信息、配置项等。
  • List(列表):实现双向链表,支持在头部或尾部插入、删除元素,适用于消息队列、任务列表等。
  • Set(集合):无序唯一元素集合,适合存储标签、去重操作。
  • Sorted Set(有序集合):类似Set,但每个成员带有分数,可用于排行榜、带权重的数据集。
  • Hash(哈希):存储键值对的集合,非常适合对象属性的批量操作。

2. 高性能与高并发

Redis 以其极高的读写性能和每秒百万级别的并发处理能力著称。 内存数据结构、单线程模型(直至v6版本)、非阻塞I/O以及高效的网络通信使得Redis成为缓存技术的首选之一。

3. 持久化与分布式特性

Redis 提供了RDB(快照)和AOF(追加日志)两种持久化机制,确保数据在断电或重启后得以恢复。 同时,Redis 支持主从复制、哨兵模式和集群模式,能够实现数据的冗余备份、故障转移及分布式缓存,满足大规模、高可用场景的需求。

17.3 不同类型的缓存技术对比

1. 本地缓存 vs 分布式缓存

本地缓存(如Java中的HashMap.NETMemoryCache)存在于应用服务器内存中,速度快,但仅限于单机使用,容量受服务器限制,且存在单点风险。

分布式缓存(如Redis、Memcached)部署在独立的服务器集群中,支持多节点共享数据,容量可扩展,具备容错性和高可用性,但需考虑数据一致性、网络开销等问题。

2. Redis vs Memcached

尽管两者均为分布式缓存,Redis 在数据类型、持久化、事务支持等方面更胜一筹。Memcached 专注于简单键值存储,性能极高但功能较为单一,适合对缓存需求简单、注重极致性能的场景。


代码示例(以Python为例)

import redis# 连接Redis
r = redis.Redis(host='localhost', port=6379, db=0)# 设置缓存数据(String类型)
r.set('user:1', '{"name": "Alice", "age": 30}')# 读取缓存数据
user_data = r.get('user:1')
print(user_data.decode('utf-8'))  # 输出:{"name": "Alice", "age": 30}# 使用List作为消息队列
r.rpush('task_queue', 'Task A')
r.rpush('task_queue', 'Task B')# 弹出任务
first_task = r.lpop('task_queue')
print(first_task.decode('utf-8'))  # 输出:Task A

17.4 缓存机制在Java Spring框架中的应用

缓存机制在Java Spring框架中扮演着关键角色,通过有效利用缓存技术,开发者能够显著提升应用程序的性能、降低数据库负载,并提高整体系统的响应速度。Spring为开发者提供了灵活且易于集成的缓存抽象层,允许应用程序以声明式的方式利用各种缓存技术,如Redis、EhCache、Caffeine等。以下是Spring中缓存机制的主要组成部分、使用方法以及应用场景。

一、Spring缓存抽象层

Spring从3.1版本开始引入了基于注解的缓存支持,为开发者提供了一套通用的缓存API和注解,使得应用程序可以与具体的缓存实现解耦。主要特点包括:

1. 声明式缓存

Spring通过一系列注解(如@Cacheable@CacheEvict@CachePut)来标记需要进行缓存操作的方法,无需硬编码缓存逻辑,保持业务代码的整洁。

  • @Cacheable:标记方法的返回结果应当被缓存,后续相同参数的调用将直接从缓存中获取结果,避免重复计算或数据库查询。
  • @CacheEvict:用于清除缓存中的特定条目,通常在更新或删除操作后触发,确保缓存与数据源的一致性。
  • @CachePut:即使方法返回结果不直接返回给客户端,也依然将其存入缓存,常用于异步更新缓存。

2. 可插拔的缓存提供商

Spring缓存抽象层允许无缝切换不同的缓存实现。只需配置合适的缓存管理器(如RedisCacheManagerEhCacheCacheManager),并通过@EnableCaching开启缓存支持,即可使用对应的缓存技术。

二、Spring Boot与缓存集成

在Spring Boot环境中,集成缓存更为便捷。通过添加相应的starter依赖(如spring-boot-starter-data-redisspring-boot-starter-cache搭配spring-boot-starter-data-ehcache),自动配置会帮助设置好必要的缓存基础设施。

1. 选择缓存技术

Spring Boot支持多种缓存技术的集成,包括但不限于:

  • Redis:高性能的内存数据结构存储,常用于分布式缓存。通过添加spring-boot-starter-data-redis依赖,Spring Boot会自动配置Redis连接、序列化器等,并提供RedisTemplateStringRedisTemplate供应用程序直接使用。

  • Ehcache:基于Java的进程内缓存解决方案,适用于单机环境。通过引入spring-boot-starter-cachespring-boot-starter-data-ehcache,Spring Boot将自动配置Ehcache,并提供缓存管理器。

  • Caffeine:高效的本地缓存库,适用于高并发场景。引入spring-boot-starter-cachespring-boot-starter-data-caffeine,Spring Boot将自动配置Caffeine缓存。

  • Hazelcast:分布式内存计算平台,也可作为缓存使用。通过spring-boot-starter-cachespring-boot-starter-data-hazelcast,Spring Boot将自动配置Hazelcast缓存。
    2. 配置缓存

application.propertiesapplication.yml中配置缓存相关参数,如Redis服务器地址、端口、密码,或者Ehcache的配置文件路径等。Spring Boot会根据这些配置自动连接到缓存服务。

3. 使用Spring Cache抽象

Spring Cache提供了一套通用的缓存抽象,使得应用程序与具体的缓存技术解耦。主要通过以下几个方面实现:
a) @EnableCaching注解

在主配置类(如Application类)上添加@EnableCaching注解,启用Spring Cache功能。

b) @Cacheable@CacheEvict@CachePut等注解

  • @Cacheable:标记在方法上,表示该方法的返回结果应当被缓存。如果缓存中存在匹配的键,则直接从缓存返回结果,否则执行方法并将结果放入缓存。
@Service
public class UserService {@Cacheable(value = "users", key = "#userId")public User findUserById(Long userId) {// 查询数据库或其他耗时操作return userRepository.findById(userId).orElse(null);}
}
  • @CacheEvict:用于清除缓存。可以指定在方法执行前或执行后清除缓存,以及清除单个条目还是整个缓存。
@Service
public class UserService {@CacheEvict(value = "users", key = "#userId")public void updateUser(User user) {userRepository.save(user);}
}
  • @CachePut:在方法执行后更新缓存,无论方法是否引发异常。常用于数据更新后同步缓存的情况。
@Service
public class UserService {@CachePut(value = "users", key = "#user.id")public User updateUser(User user) {return userRepository.save(user);}
}

c) 缓存命名与键生成

  • 缓存名称:在注解中指定,如@Cacheable("users")。可以定义多个缓存,分别存放不同类型的数据。

  • 缓存键:通过key属性指定,支持SpEL表达式。如key="#userId"表示使用方法参数作为缓存键。可以灵活定义复杂的键生成策略,如结合多个参数或使用方法名。

d) 自定义缓存配置

如果需要更精细的控制,可以自定义CacheManagerCacheResolver,或者使用CachingConfigurer接口来自定义全局缓存配置。

4. 整合特定缓存技术

以Redis为例,Spring Boot自动配置的RedisTemplateStringRedisTemplate可以直接用于操作Redis缓存。若要使用Spring Cache抽象,还需要配置RedisCacheManager,使其与Spring Cache体系对接。

@Configuration
@EnableCaching
public class RedisCacheConfig extends CachingConfigurerSupport {@Autowiredprivate RedisConnectionFactory connectionFactory;@Overridepublic CacheManager cacheManager() {RedisCacheConfiguration config = RedisCacheConfiguration.defaultCacheConfig().entryTtl(Duration.ofMinutes(30)) // 设置缓存过期时间.disableCachingNullValues(); // 不缓存null值return RedisCacheManager.builder(connectionFactory).cacheDefaults(config).transactionAware() // 支持事务.build();}
}

通过上述步骤,Spring Boot应用便成功集成了缓存功能,能够在需要的地方透明地使用缓存加速数据访问,同时保持与具体缓存技术的松耦合。开发者可以根据业务需求和性能指标选择最适合的缓存技术和配置。

三、配置与使用示例

1. 配置

application.propertiesapplication.yml中配置缓存提供商的相关参数。例如,使用Redis作为缓存:

spring.redis.host=localhost
spring.redis.port=6379

或者在Spring Boot的Java配置类中启用缓存:

@Configuration
@EnableCaching
public class CacheConfig {// 可在此配置缓存管理器、自定义缓存键生成策略等
}

2. 使用示例

假设有一个UserService接口,其中的getUserById方法希望利用缓存:

@Service
public class UserServiceImpl implements UserService {@Autowiredprivate UserRepository userRepository;@Cacheable(value = "users", key = "#id")public User getUserById(Long id) {return userRepository.findById(id).orElse(null);}@CacheEvict(value = "users", key = "#user.id")public void updateUser(User user) {userRepository.save(user);}
}

在这个例子中:

  • getUserById方法被@Cacheable注解标记,缓存键为用户ID。首次调用时,方法会执行数据库查询;后续相同的ID查询将直接从名为“users”的缓存中获取结果。
  • updateUser方法在保存用户后,使用@CacheEvict清除对应用户ID的缓存条目,确保缓存数据与更新后的数据库记录一致。

17.5 应用场景

Spring缓存机制适用于多种场景:

  • 数据查询密集型应用:如电商平台的商品详情页、内容管理系统的文章列表等,通过缓存经常访问且变化不频繁的数据,避免频繁查询数据库。
  • 实时统计与分析:如网站访问量、用户行为统计数据等,可以使用缓存暂存计算结果,减少实时计算的压力。
  • 会话管理:利用缓存(如Redis)存储用户会话信息,实现跨节点的会话共享,支持高并发、分布式环境下的用户登录状态管理。
  • API限速与计数:利用缓存(如Redis的原子操作)进行API调用次数统计与速率限制。

17.6 注意事项

  • 缓存与数据一致性:缓存与数据库之间可能存在数据不一致的风险。应根据业务需求设计合理的缓存更新策略(如同步更新、定时刷新、消息驱动等)以及处理缓存击穿、雪崩等问题。
  • 缓存过期策略:设置合适的缓存过期时间,平衡数据新鲜度与缓存命中率。
  • 缓存容量管理:监控缓存使用情况,防止缓存溢出,并根据实际情况调整缓存淘汰策略。

综上,Java Spring框架提供的缓存机制为开发者提供了一种简便、高效的手段来提升应用性能。通过合理运用缓存注解、选择适当的缓存实现以及精心设计缓存策略,可以显著降低数据库负载,提高用户体验。

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

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

相关文章

Xbox VR头盔即将推出,但它是Meta Quest的‘限量版’。

📳Xbox VR头盔即将推出,但它是Meta Quest的‘限量版’。 微软与Meta合作推出限量版Meta Quest VR头映射Xbox风格,可能是Meta Quest 3或未来版本的特别定制版,附带Xbox控制器。这一合作是Meta向第三方硬件制造商开放其Quest VR头盔…

conda出现http429报错:CondaHTTPError: HTTP 429 TOO MANY REQUESTS for url <xxx>

我的报错信息如下&#xff1a; CondaHTTPError: HTTP 429 TOO MANY REQUESTS for url <https://mirrors.ustc.edu.cn/anaconda/pkgs/main/linux-64/current_repodata.json> Elapsed: 00:46.305607An HTTP error occurred when trying to retrieve this URL. HTTP errors…

ros程序项目打包deb 详细过程以及报错解决

需要注意,最好是 ubuntu 20的 系统, 18 的系统支持不足够 CMakeLists.txt 最后添加, xxxxx 是你的节点或者程序的名称,也就是最后运行的ros节点名称: install(TARGETS xxxxxx ARCHIVE DESTINATION ${CATKIN_PACKAGE_LIB_DESTINATION} LIBRARY DESTINATION ${CATKI…

C语言如何⽤指针表示多维数组?

一、问题 如何⽤指针表示多维数组&#xff1f; 二、解答 这⾥就是以⼆维数组为例进⾏多维数组的操作演示。 ⾸先定义⼀个⼆维数组 int a[3][3] &#xff0c;数组名代表的是数组的起始地址&#xff0c;因此数组名 a 和第⼀个元素 a[0][0] 的地址是相同的&#xff0c;但是意义却…

小塔 | 时尚领域RFID应用,别人早你一步!

优衣库&#xff0c;作为知名服装品牌零售商&#xff0c;近年来在数字化转型的道路上取得了显著的成果。其中&#xff0c;RFID技术的应用成为了优衣库提升运营效率、优化客户体验以及实现精准营销的重要工具。 RFID助力时尚门店品牌升级 优衣库深知RFID技术的潜力&#xff0c;将…

计算机网络3——数据链路层3以太网的MAC层

文章目录 一、MAC 层的硬件地址1、介绍2、注意点3、定制标准 二、MAC 帧的格式1、结构2、工作原理3、其他 一、MAC 层的硬件地址 1、介绍 在局域网中&#xff0c;硬件地址又称为物理地址或 MAC地址(因为这种地址用在MAC帧中)。 大家知道&#xff0c;在所有计算机系统的设计中…

计算机视觉——两视图几何求解投影矩阵

上文我提到了通过图像匹配得到基本矩阵&#xff0c;接下来我们要接着求解投影矩阵。 计算投影矩阵思路 假设两个投影矩阵为规范化相机&#xff0c;因此采用基本矩阵进行恢复。在规范化相机下&#xff0c; P [ I ∣ 0 ] P[I|0] P[I∣0], P ′ [ M ∣ m ] P[M|m] P′[M∣m]。…

apache和IIS区别?内网本地服务器项目怎么让外网访问?

Apache和IIS是比较常用的搭建服务器的中间件&#xff0c;它们之间还是有一些区别差异的&#xff0c;下面就详细说说 Apache和IIS有哪些区别&#xff0c;以及如何利用快解析实现内网主机应用让外网访问。 首先说说apache和IIS最基本的区别。Apache运行的操作系统通常为Unix或Lin…

Mysql — 刷题知识点

一. 功能函数 1. 大小写转换 UCASE/LCASE (列名) LCASE是将内容转换为小写 UCASE将内容转换为大写 CASE是条件控制语句的关键字 二、join ... on 问题 1. right join ..on RIGHT JOIN 关键字会返回右表 (t2) 所有的行&#xff0c;即使在左表 (t1) 中没有匹配的行。或者更…

[C++]多态是如何调用不同的函数对象的?

多态调用不同的函数对象涉及C中的虚函数表&#xff08;VTable&#xff09;、虚函数指针&#xff08;VPtr&#xff09;以及动态绑定机制。下面详细解析这一底层逻辑&#xff1a; 1. 虚函数表&#xff08;VTable&#xff09;与虚函数指针&#xff08;VPtr&#xff09; 在C中&…

【每日刷题】Day22

【每日刷题】Day22 &#x1f955;个人主页&#xff1a;开敲&#x1f349; &#x1f525;所属专栏&#xff1a;每日刷题&#x1f34d; &#x1f33c;文章目录&#x1f33c; 1. 1669. 合并两个链表 - 力扣&#xff08;LeetCode&#xff09; 2. 11. 盛最多水的容器 - 力扣&#…

回归用户本真的业务价值需求,聚焦成本优化与内核能力提升——专访云和恩墨张程伟、金毅...

数据库作为企业核心业务系统的重要基座&#xff0c;其技术架构和性能都将直接影响企业的运营效率与成本。在2024“数据技术嘉年华”大会现场&#xff0c;笔者采访到了云和恩墨本原数据的两位技术合伙人——MogDB数据库研发负责人张程伟、下一代原生HTAP企业级数据库研发负责人金…

Process in Semiconductor(半导体工艺)

Front-End Process in Semiconductor 引言正文Front-endBack-endFront-end of lineProcess flowBack-end of lineSiN seal layerCVDLPCVDPECVDSOI PSVSOI ACTSOI PSV+引言

语音生成表情SlefTalk

目录 SlefTalk官网 依赖项安装 windows安装psbody templates.pkl 下载地址&#xff1a; 推理代码&#xff1a; diffspeaker SlefTalk官网 GitHub - psyai-net/SelfTalk_release: This is the official source for our ACM MM 2023 paper "SelfTalk: A Self-Supervi…

NSQ消息队列---总结篇

架构 概念 nsqlookup&#xff1a;存储了nsqd的元数据和服务信息(endpoind),向消费者提供服务发现功能, 向nsqadmin提供数据查询功能。 nsqd: 是接收、队列和传送消息到客户端的守护进程。 nsqadmin&#xff1a;简单的管理界面,展示了topic, channel以及channel上的消费者,也…

【漏洞复现】号卡极团管理系统 index.php SQL注入漏洞

0x01 产品简介 号卡极团管理系统是一款专为号卡行业打造的管理系统&#xff0c;它具备一系列强大的功能&#xff0c;能够满足号卡行业推广人员在业务运营中的各类需求。 0x02 漏洞概述 号卡极团管理系统存在SQL注入漏洞&#xff0c;未授权的攻击者可以通过该漏洞获取数据库敏…

Playwright

一&#xff1a;选择器 个人理解&#xff0c;其实跟css选择器一样 1、某个类的第一个 .your-class-name:first-of-type2、某个类的第一个子元素 :first-child

数据库关系模式分解 - 无损连接和保持函数依赖性

文章目录 1 概述1.1 关系模式分解的好坏标准 2 无损连接验证算法 1 概述 1.1 关系模式分解的好坏标准 书上的算法太抽象了&#xff0c;咱不好理解&#xff0c;以下举例说明。一个关系可以有很多种分解方法&#xff0c;如何判断分解的好与坏呢&#xff1f; ① 查询时的连接操作…

类的六个构造函数相关干货

构造函数 特点 1.名字与类名相同 2.无返回值 3.对象实例化的时候编译器自动调用这个函数 4.构造函数可以重载&#xff08;无参构造函数&#xff0c;拷贝构造等&#xff09; 5.如果类中没有显式定义构造函数&#xff08;深拷贝&#xff09;&#xff0c;则编译器会自动生成一个…

CSS基础——2.CSS选择器

1. 通用选择器 通用选择器用星号*表示,它不匹配某个特定的 HTML 元素,而是匹配 HTML 文档中的每个元素,开发中通常使用通用选择器来清除 HTML元素中默认的内外边距 通用选择器格式:*{} * { margin: 0 auto; padding: 0; } 2. 标签选择器 根据标签的名字 进行选择匹…