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 依赖:

org.springframework.boot spring-boot-starter-cache org.ehcache ehcache 1.2 配置 Ehcache 在 src/main/resources 目录下创建 ehcache.xml 文件:




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 依赖:

org.springframework.boot spring-boot-starter-cache com.github.ben-manes.caffeine caffeine 2.2 启用缓存 在 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);
}
}
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 依赖:

org.springframework.boot spring-boot-starter-cache com.google.guava guava 3.2 启用缓存 在 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);
}
}
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 等。然而,凡事有利就有弊,那么多级缓存最大的问题就是数据一致性问题,对于多级缓存的数据一致性问题要如何保证呢?

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

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

相关文章

linux tigerVNC使用

简介 TigerVNC是VNC的一种高性能、平台中立实现(虚拟网络计算),一种客户端/服务器应用程序,允许用户启动远程图形应用程序并与之交互机器。TigerVNC提供运行所需的性能级别3D和视频应用程序,并尝试保持普通外观并尽可…

基于redis实现API接口访问次数限制

一,概述 日常开发中会有一个常见的需求,需要限制接口在单位时间内的访问次数,比如说某个免费的接口限制单个IP一分钟内只能访问5次。该怎么实现呢,通常大家都会想到用redis,确实通过redis可以实现这个功能&#xff0c…

uni-app小程序开发(1)

下载软件就不多赘述了。 直接上代码,写过wep端的vue看这个小程序就简单很多,不需要搞那么多麻烦事情,直接编译器就创建好了基础模版。 1、项目结构 暂时知道这么多,后续再补充 2、页面创建、导航栏设置、基础属性设置 在pages中…

【C++】哈希表封装 unordered_map 和 unordered_set 的实现过程

C语法相关知识点可以通过点击以下链接进行学习一起加油!命名空间缺省参数与函数重载C相关特性类和对象-上篇类和对象-中篇类和对象-下篇日期类C/C内存管理模板初阶String使用String模拟实现Vector使用及其模拟实现List使用及其模拟实现容器适配器Stack与QueuePriori…

优化策略:揭秘钢条切割与饼干分发的算法艺术

引言 在生活中,钢条和饼干看似风马牛不相及,但它们的分割与分发却隐藏着惊人的数学魅力。如何最大化利润?如何用有限的资源最大程度满足需求?这便是算法世界中的艺术。今天,我们来揭秘钢条切割与饼干分发的算法设计。本…

SQL,力扣题目1709,访问日期之间最大的空档期

一、力扣链接 LeetCode_1709 二、题目描述 表: UserVisits ------------------- | Column Name | Type | ------------------- | user_id | int | | visit_date | date | ------------------- 该表没有主键,它可能有重复的行 该表包含用户访问…

第七篇: BigQuery中的复杂SQL查询

BigQuery中的复杂SQL查询 背景与目标 在数据分析中,我们通常需要从多个数据源中获取信息,以便进行深入的分析。这时,BigQuery提供的JOIN、UNION和子查询等复杂SQL语句非常实用。本文将以Google BigQuery的公共数据集为例,介绍如何…

【C++】条件变量condition_variable

文章目录 1. 条件变量定义及特点2. 代码示例3. wait方法4. wait_for方法5. notify_all和notify_one6. 思考 1. 条件变量定义及特点 条件变量 用于在线程之间协调共享资源的访问。它允许一个线程等待特定条件的满足(如某个值的变化),而另一个线程在条件满足时通知(或…

C++ 线程初始化编译报错

这是一个很简单的开启一个线程, 用于演示一个线程和生命周期之间的错误,但是还没有把这个错误暴露出来, 就遇见了一个编译问题. 线程中执行指定逻辑的代码 线程的执行方法, 声明写在了ThreadRun.h 实现写在 ThreadRun.cpp中. class ThreadRun { public: void func(); };void T…

SPIRE: Semantic Prompt-Driven Image Restoration 论文阅读笔记

这是一篇港科大学生在google research 实习期间发在ECCV2024的语义引导生成式修复的文章,港科大陈启峰也挂了名字。从首页图看效果确实很惊艳,尤其是第三行能用文本调控修复结果牌上的字。不过看起来更倾向于生成,对原图内容并不是很复原&…

Backend - Python 爬取网页数据并保存在Excel文件中

目录 一、导入依赖 二、前端爬取页面数据 1. html 中 2. js 中 三、后端获取数据,并存储到 Excel 文件中 1. 后端接收数据 2. 后端存储数据 (1)系统代码固定存储位置 (2)用户可选择文件对话框的存储位置 一、…

Dubbo负载均衡

负载均衡策略与配置细节 Dubbo 内置了 client-based 负载均衡机制,如下是当前支持的负载均衡算法,结合上文提到的自动服务发现机制,消费端会自动使用 Weighted Random LoadBalance 加权随机负载均衡策略 选址调用。 如果要调整负载均衡算法…

软件工程中的创建型设计模式:工厂方法模式与抽象工厂模式

目录 1. 工厂方法模式(Factory Method Pattern) 1.1 核心概念 1.2 应用场景 1.3 优点 2. 抽象工厂模式(Abstract Factory Pattern) 2.1 核心概念 2.2 应用场景 2.3 优点 3. 联系与区别 4. 拓展知识 5. 结语 在软件工程…

FFmpeg 4.3 音视频-多路H265监控录放C++开发十二:在屏幕上显示多路视频播放,可以有不同的分辨率,格式和帧率。

上图是在安防领域的要求,一般都是一个屏幕上有显示多个摄像头捕捉到的画面,这一节,我们是从文件中读取多个文件,显示在屏幕上。 一 改动UI文件 这里我们要添加两个label,为了区分我们设置一下背景色(这个是…

java中线程与集合的面试题

在 Java 面试中,线程和集合相关的知识是非常常见的考察点。以下是几个典型的问题及答案: 线程相关面试题 什么是线程? 线程是操作系统能够进行运算调度的最小单位。它被包含在进程之中,是进程中的实际运作单位。一个进程可以有多…

前言2、VS(Visual Studio)-2022使用

早前用VS-2010编译平台,进行C语言编程学习。 现如今,为了适应未来发展趋势以及日新月异的新功能,就此转到VS-2022编译平台; 由于都是VS编译平台,大多数基础功能都类似,关于一些基础操作可参考前言1&#…

深入了解逻辑回归:机器学习中的经典算法

✅作者简介:2022年博客新星 第八。热爱国学的Java后端开发者,修心和技术同步精进。 🍎个人主页:Java Fans的博客 🍊个人信条:不迁怒,不贰过。小知识,大智慧。 💞当前专栏…

Tomcat(3) Tomcat是哪种类型的服务器?

Tomcat是一个开源的Java Servlet容器,同时也是一个轻量级的Web服务器。它主要用于实现Java Servlet和JavaServer Pages (JSP)规范,使得开发者能够部署和运行Java Web应用程序。 Tomcat的主要类型 1. Servlet容器 Tomcat的核心功能之一是作为Servlet容…

软件测试基础十四(python 类与对象)

类与对象的意义 面向对象编程的基础 模拟现实世界:在Python中,类和对象是面向对象编程(OOP)的核心概念。类就像是制造对象的蓝图或者模板,它定义了对象的属性(数据成员)和方法(函数…

技术总结(二十二)

一、Redis缓存更新 在更新Redis缓存时,通常有两种策略: 更新缓存(Cache-Aside Pattern):先从缓存获取数据,如果缓存中没有数据或数据已经过期,则从数据库中获取最新数据,并更新到缓…