redis与本地缓存
本地缓存是将数据存储在应用程序所在的本地内存中的缓存方式。既然,已经有了 Redis 可以实现分布式缓存了,为什么还需要本地缓存呢?接下来,我们一起来看。
为什么需要本地缓存?
尽管已经有 Redis 缓存了,但本地缓存也是非常有必要的,因为它有以下优点:
速度优势:本地缓存直接利用本地内存,访问速度非常快,能够显著降低数据访问延迟。
减少网络开销:使用本地缓存可以减少与远程缓存(如 Redis)之间的数据交互,从而降低网络 I/O 开销。
降低服务器压力:本地缓存能够分担服务器的数据访问压力,提高系统的整体稳定性。
因此,在生产环境中,我们通常使用本地缓存+Redis 缓存一起组合成多级缓存,来共同保证程序的运行效率。
多级缓存
多级缓存是一种缓存架构策略,它使用多个层次的缓存来存储数据,以提高数据访问速度和系统性能,最简单的多级缓存就是由本地缓存 + Redis 分布式缓存组成的,如图所示:
多级缓存在获取时的实现代码如下:
public Object getFromCache(String key) {
// 先从本地缓存中查找
Cache.ValueWrapper localCacheValue = cacheManager.getCache(“localCache”).get(key);
if (localCacheValue!= null) {
return localCacheValue.get();
}
// 如果本地缓存未命中,从 Redis 中查找
Object redisValue = redisTemplate.opsForValue().get(key);
if (redisValue!= null) {
// 将 Redis 中的数据放入本地缓存
cacheManager.getCache(“localCache”).put(key, redisValue);
return redisValue;
}
return null;
}
本地缓存的实现
本地缓存常见的方式实现有以下几种:
Ehcache
Caffeine
Guava Cache
它们的基本使用如下。
1.Ehcache
1.1 添加依赖
在 pom.xml 文件中添加 Ehcache 依赖:
1.3 启用缓存
在 Spring Boot 应用的主类或配置类上添加 @EnableCaching 注解:
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cache.annotation.EnableCaching;
@SpringBootApplication
@EnableCaching
public class CacheApplication {
public static void main(String[] args) {
SpringApplication.run(CacheApplication.class, args);
}
}
1.4 使用缓存
创建一个服务类并使用 @Cacheable 注解:
import org.springframework.cache.annotation.Cacheable;
import org.springframework.stereotype.Service;
@Service
public class MyService {
@Cacheable(value = "myCache", key = "#id")
public String getData(String id) {// 模拟耗时操作try {Thread.sleep(1000);} catch (InterruptedException e) {e.printStackTrace();}return "Data for " + id;
}
}
2.Caffeine
2.1 添加依赖
在 pom.xml 文件中添加 Caffeine 依赖:
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cache.annotation.EnableCaching;
@SpringBootApplication
@EnableCaching
public class CacheApplication {
public static void main(String[] args) {
SpringApplication.run(CacheApplication.class, args);
}
}
2.3 配置 Caffeine 缓存
创建一个配置类来配置 Caffeine 缓存:
import com.github.benmanes.caffeine.cache.Caffeine;
import org.springframework.cache.CacheManager;
import org.springframework.cache.caffeine.CaffeineCacheManager;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
@Configuration
public class CacheConfig {
@Bean
public CacheManager cacheManager() {CaffeineCacheManager cacheManager = new CaffeineCacheManager("myCache");cacheManager.setCaffeine(Caffeine.newBuilder().maximumSize(1000).expireAfterWrite(120, TimeUnit.SECONDS));return cacheManager;
}
}
2.4 使用缓存
创建一个服务类并使用 @Cacheable 注解:
import org.springframework.cache.annotation.Cacheable;
import org.springframework.stereotype.Service;
@Service
public class MyService {
@Cacheable(value = "myCache", key = "#id")
public String getData(String id) {// 模拟耗时操作try {Thread.sleep(1000);} catch (InterruptedException e) {e.printStackTrace();}return "Data for " + id;
}
}
3.Guava Cache
3.1 添加依赖
在 pom.xml 文件中添加 Guava 依赖:
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cache.annotation.EnableCaching;
@SpringBootApplication
@EnableCaching
public class CacheApplication {
public static void main(String[] args) {
SpringApplication.run(CacheApplication.class, args);
}
}
3.3 配置 Guava 缓存
创建一个配置类来配置 Guava 缓存:
import com.google.common.cache.CacheBuilder;
import org.springframework.cache.Cache;
import org.springframework.cache.CacheManager;
import org.springframework.cache.concurrent.ConcurrentMapCache;
import org.springframework.cache.concurrent.ConcurrentMapCacheManager;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import java.util.concurrent.TimeUnit;
@Configuration
public class CacheConfig {
@Bean
public CacheManager cacheManager() {ConcurrentMapCacheManager cacheManager = new ConcurrentMapCacheManager() {@Overrideprotected Cache createConcurrentMapCache(String name) {return new ConcurrentMapCache(name,CacheBuilder.newBuilder().maximumSize(1000).expireAfterWrite(120, TimeUnit.SECONDS).build().asMap(), false);}};return cacheManager;
}
}
3.4 使用缓存
创建一个服务类并使用 @Cacheable 注解:
import org.springframework.cache.annotation.Cacheable;
import org.springframework.stereotype.Service;
@Service
public class MyService {
@Cacheable(value = "myCache", key = "#id")
public String getData(String id) {// 模拟耗时操作try {Thread.sleep(1000);} catch (InterruptedException e) {e.printStackTrace();}return "Data for " + id;
}
}
知识扩展:@Cacheable、@CachePut、@CacheEvict
在 Spring 框架中,@Cacheable、@CachePut 和 @CacheEvict 是用于缓存管理的注解,它们的含义如下:
@Cacheable:用于声明一个方法的返回值是可以被缓存的。当方法被调用时,Spring Cache 会先检查缓存中是否存在相应的数据。如果存在,则直接返回缓存中的数据,避免重复执行方法;如果不存在,则执行方法并将返回值存入缓存中。它的使用示例如下:
@Cacheable(value = “users”, key = “#id”)
public User getUserById(String id) {
// 模拟从数据库中获取用户信息
System.out.println("Fetching user from database: " + id);
return new User(id, "User Name " + id);
}
@CachePut:用于更新缓存中的数据。与 @Cacheable 不同,@CachePut 注解的方法总是会执行,并将返回值更新到缓存中。无论缓存中是否存在相应的数据,该方法都会执行,并将新的数据存入缓存中(如果缓存中已存在数据,则覆盖它)。它的使用示例如下:
@CachePut(value = “users”, key = “#user.id”)
public User updateUser(User user) {
// 模拟更新数据库中的用户信息
System.out.println("Updating user in database: " + user.getId());
// 假设更新成功
return user;
}
@CacheEvict:用于删除缓存中的数据。当方法被调用时,指定的缓存项将被删除。这可以用于清除旧数据或使缓存项失效。它的使用示例如下:
@CacheEvict(value = “users”, key = “#id”)
public void deleteUser(String id) {
// 模拟从数据库中删除用户信息
System.out.println("Deleting user from database: " + id);
}
// 清除整个缓存,而不仅仅是特定的条目
@CacheEvict(value = “users”, allEntries = true)
public void clearAllUsersCache() {
System.out.println(“Clearing all users cache”);
}
小结
生产环境通常会使用本地缓存 + Redis 缓存,一起实现多级缓存,以提升程序的运行效率,而本地缓存的常见实现有 Ehcache、Caffeine、Guava Cache 等。然而,凡事有利就有弊,那么多级缓存最大的问题就是数据一致性问题,对于多级缓存的数据一致性问题要如何保证呢?
相关文章:
redis与本地缓存
本地缓存是将数据存储在应用程序所在的本地内存中的缓存方式。既然,已经有了 Redis 可以实现分布式缓存了,为什么还需要本地缓存呢?接下来,我们一起来看。 为什么需要本地缓存? 尽管已经有 Redis 缓存了,但…...
git撤销commit和add
撤销commit git reset --soft HEAD^撤销add git reset .查看状态 git status...

【361】基于springboot的招生宣传管理系统
摘 要 使用旧方法对招生宣传管理系统的信息进行系统化管理已经不再让人们信赖了,把现在的网络信息技术运用在招生宣传管理系统的管理上面可以解决许多信息管理上面的难题,比如处理数据时间很长,数据存在错误不能及时纠正等问题。这次开发的招…...
【一些关于Python的信息和帮助】
Python是一种广泛使用的高级编程语言,它的设计哲学强调代码的可读性和简洁的语法(尤其是使用空格缩进划分代码块,而不是使用大括号或关键字)。Python支持多种编程范式,包括面向对象、命令式、函数式和过程式编程。 以…...

creo toolkit二次开发学习之程序集(ProAsmcomp)和装配体组件路径对象(ProAsmcomppath)
程序集ProAsmcomp可以理解为装配体组件对象。 对象ProAssembly是ProSolid的一个实例,并共享相同的声明。因此,ProAssembly对象可以作为适用于装配体的任何ProSolid和ProMdl函数的输入。特别是,因为你可以使用函数ProSolidFeatVisit()来遍历特…...

深入浅出 Spring Boot 与 Shiro:构建安全认证与权限管理框架
一、Shiro框架概念 (一)Shiro框架概念 1.概念: Shiro是apache旗下一个开源安全框架,它对软件系统中的安全认证相关功能进行了封装,实现了用户身份认证,权限授权、加密、会话管理等功能,组成一…...

外包干了三年,精神严重内耗...
前段时间我同事(做测试的一个妹子)跟我讲,感觉早上起来十分的疲惫,不想上班,问我们这是什么样的现象,其实有时候我也有这种感觉,虽然我卷,但我也是肉体凡胎啊!不是机器人…...

ruoyi-vue集成tianai-captcha验证码
后端代码 官方使用demo文档:http://doc.captcha.tianai.cloud/#%E4%BD%BF%E7%94%A8demo 我的完整代码:https://gitee.com/Min-Duck/RuoYi-Vue.git 主pom.xml 加入依赖 <!-- 滑块验证码 --><dependency><groupId>cloud.tianai.captc…...

Django安装
在终端创建django项目 1.查看自己的python版本 输入对应自己本机python的版本,列如我的是3.11.8 先再全局安装django依赖包 2.在控制窗口输入安装命令: pip3.11 install django 看到Successflully 说明我们就安装成功了 python的Scripts文件用于存…...

Ubuntu 20.04 安装 QGC v4.3 开发环境
Ubuntu 20.04 安装 QGC开发环境 1. 准备安装 Qt 5.15.2安装依赖获取源码 2. 编译参考 前言 QGC ( QGroundControl) 是一个开源地面站,基于QT开发的,有跨平台的功能。可以在Windows,Android,MacOS或Linux上运行。它可以将PX4固件加…...

WPF+MVVM案例实战(二十一)- 制作一个侧边弹窗栏(AB类)
文章目录 1、案例效果1、侧边栏分类2、AB类侧边弹窗实现1.文件创建2、样式代码与功能代码实现3、功能代码实现 3 运行效果4、源代码获取 1、案例效果 1、侧边栏分类 A类 :左侧弹出侧边栏B类 :右侧弹出侧边栏C类 :顶部弹出侧边栏D类 …...
linux中怎样登录mysql数据库
在Linux中登录MySQL数据库,可以使用以下命令: mysql -u username -p 其中,username是你的MySQL用户名。运行该命令后,系统会提示你输入密码。 如果MySQL服务器不在本地主机或者你需要指定不同的端口,可以使用以下命…...
深入理解 Linux 内存管理:free 命令详解
在 Linux 系统中,内存是关键的资源之一,管理和监控内存的使用情况对系统的稳定性和性能至关重要。free 命令是 Linux 中用于查看内存使用情况的重要工具,它可以让我们快速了解系统中物理内存和交换分区(Swap)的使用状态…...

指针万字超级最强i解析与总结!!!!!
文章目录 1.内存和地址1.1内存1.2究竟该如何理解编址 2.指针变量和地址2.1 取地址操作符(&)2.2指针变量和解引用操作符(*)2.2.1指针变量2.2.2如何拆解指针类型2.2.3解引用操作符 2.3 指针变量的大小 3.指针变量类型的意义3.1指…...

告别生硬电子音,这款TTS软件让语音转换更自然动听
Balabolka是一款革新性的文本语音转换工具,为用户提供了极其灵活和个性化的阅读体验。这款软件不仅仅是简单的文字朗读器,更是一个智能的语音助手,能够将各类文本瞬间转化为生动自然的语音输出。 软件的核心优势在于其卓越的文件兼容性和多样…...
CORS(跨域资源共享)和SOP(同源策略)
CORS(跨域资源共享)和SOP(同源策略)不是同一个东西,但它们紧密相关,并且常常一起讨论,因为 CORS 是为了解决同源策略带来的跨域问题而引入的。 同源策略(Same-Origin Policy&#x…...
【系统设计】数据库压缩技术详解:从基础到实践(附Redis内存优化实战案例)
概述 在现代数据库系统中,压缩技术对于提高存储效率和加速查询性能至关重要。特别是在处理大规模数据时,压缩能够极大地减少存储空间,并优化查询性能。本文将总结几种常见的压缩方式,并通过详细的解释和示例清晰地展示每种压缩方…...

基于SpringBoot的“乐校园二手书交易管理系统”的设计与实现(源码+数据库+文档+PPT)
基于SpringBoot的“乐校园二手书交易管理系统”的设计与实现(源码数据库文档PPT) 开发语言:Java 数据库:MySQL 技术:SpringBoot 工具:IDEA/Ecilpse、Navicat、Maven 系统展示 系统首页界面图 用户注册界面图 二手…...

debian11安装最新rabbitmq
1、使用官网提供系统对应的安装脚本 安装 版本说明: Debian Buster代表Debian 10 Debian Bullseye代表Debian 11 Debian Bookworm代表Debian 12 Debian Trixie代表Debian 13 Debian Sid代表Debian unstable版本 2、新建脚本文件 vim rabbitMq.sh将脚本内容复制到…...
三十三、Python基础语法(面向对象其他语法-下)
一、属性划分 1.类属性 类属性:类属性就是类对象具有的属性,一般写法在类内部、方法的外部定义的变量,就是类属性,类属性在内存中只有一份。可以通过类名直接访问,也可通过实例访问。 class Circle:# 类属性,定义圆…...

解决Ubuntu22.04 VMware失败的问题 ubuntu入门之二十八
现象1 打开VMware失败 Ubuntu升级之后打开VMware上报需要安装vmmon和vmnet,点击确认后如下提示 最终上报fail 解决方法 内核升级导致,需要在新内核下重新下载编译安装 查看版本 $ vmware -v VMware Workstation 17.5.1 build-23298084$ lsb_release…...

关于iview组件中使用 table , 绑定序号分页后序号从1开始的解决方案
问题描述:iview使用table 中type: "index",分页之后 ,索引还是从1开始,试过绑定后台返回数据的id, 这种方法可行,就是后台返回数据的每个页面id都不完全是按照从1开始的升序,因此百度了下,找到了…...

成都鼎讯硬核科技!雷达目标与干扰模拟器,以卓越性能制胜电磁频谱战
在现代战争中,电磁频谱已成为继陆、海、空、天之后的 “第五维战场”,雷达作为电磁频谱领域的关键装备,其干扰与抗干扰能力的较量,直接影响着战争的胜负走向。由成都鼎讯科技匠心打造的雷达目标与干扰模拟器,凭借数字射…...
Caliper 配置文件解析:config.yaml
Caliper 是一个区块链性能基准测试工具,用于评估不同区块链平台的性能。下面我将详细解释你提供的 fisco-bcos.json 文件结构,并说明它与 config.yaml 文件的关系。 fisco-bcos.json 文件解析 这个文件是针对 FISCO-BCOS 区块链网络的 Caliper 配置文件,主要包含以下几个部…...

分布式增量爬虫实现方案
之前我们在讨论的是分布式爬虫如何实现增量爬取。增量爬虫的目标是只爬取新产生或发生变化的页面,避免重复抓取,以节省资源和时间。 在分布式环境下,增量爬虫的实现需要考虑多个爬虫节点之间的协调和去重。 另一种思路:将增量判…...

Unsafe Fileupload篇补充-木马的详细教程与木马分享(中国蚁剑方式)
在之前的皮卡丘靶场第九期Unsafe Fileupload篇中我们学习了木马的原理并且学了一个简单的木马文件 本期内容是为了更好的为大家解释木马(服务器方面的)的原理,连接,以及各种木马及连接工具的分享 文件木马:https://w…...
IP如何挑?2025年海外专线IP如何购买?
你花了时间和预算买了IP,结果IP质量不佳,项目效率低下不说,还可能带来莫名的网络问题,是不是太闹心了?尤其是在面对海外专线IP时,到底怎么才能买到适合自己的呢?所以,挑IP绝对是个技…...
音视频——I2S 协议详解
I2S 协议详解 I2S (Inter-IC Sound) 协议是一种串行总线协议,专门用于在数字音频设备之间传输数字音频数据。它由飞利浦(Philips)公司开发,以其简单、高效和广泛的兼容性而闻名。 1. 信号线 I2S 协议通常使用三根或四根信号线&a…...

[免费]微信小程序问卷调查系统(SpringBoot后端+Vue管理端)【论文+源码+SQL脚本】
大家好,我是java1234_小锋老师,看到一个不错的微信小程序问卷调查系统(SpringBoot后端Vue管理端)【论文源码SQL脚本】,分享下哈。 项目视频演示 【免费】微信小程序问卷调查系统(SpringBoot后端Vue管理端) Java毕业设计_哔哩哔哩_bilibili 项…...

力扣热题100 k个一组反转链表题解
题目: 代码: func reverseKGroup(head *ListNode, k int) *ListNode {cur : headfor i : 0; i < k; i {if cur nil {return head}cur cur.Next}newHead : reverse(head, cur)head.Next reverseKGroup(cur, k)return newHead }func reverse(start, end *ListNode) *ListN…...