1.springboot 中 RedisCacheManager rm = new RedisCacheManager(redisTemplate);我的元源码项目没这个构造
2.caffeine_redis二级缓存实现Spring接口
3.SpringBoot2.0+整合redis,使用 RedisTemplate操作redis
4.RedisCacheManager设置Value序列化器技巧
5.基于Spring Cache实现二级缓存(Caffeine+Redis)
6.SpringBoot的Cacheable缓存注解
springboot 中 RedisCacheManager rm = new RedisCacheManager(redisTemplate);我的项目没这个构造
pom.xml 引入redis 开启缓存
<!-- cache -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-cache</artifactId>
</dependency>
<!-- redis -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-redis</artifactId>
</dependency>
application.properties 配置文件
# Redis数据库索引(默认为0)spring.redis.database=0
# Redis服务器地址spring.redis.host=localhost
# Redis服务器连接端口spring.redis.port=
# Redis服务器连接密码(默认为空)spring.redis.password=
# 连接池最大连接数(使用负值表示没有限制)
spring.redis.pool.max-active=8
# 连接池最大阻塞等待时间(使用负值表示没有限制)
spring.redis.pool.max-wait=-1
# 连接池中的最大空闲连接
spring.redis.pool.max-idle=8
# 连接池中的最小空闲连接
spring.redis.pool.min-idle=0
# 连接超时时间(毫秒)
spring.redis.timeout=0
添加cache的配置类
package www.ijava.com.configure;
import com.fasterxml.jackson.annotation.JsonAutoDetect;
import com.fasterxml.jackson.annotation.PropertyAccessor;
import com.fasterxml.jackson.databind.ObjectMapper;
import java.lang.reflect.Method;
import org.springframework.cache.CacheManager;
import org.springframework.cache.annotation.CachingConfigurerSupport;
import org.springframework.cache.annotation.EnableCaching;
import org.springframework.cache.interceptor.KeyGenerator;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.data.redis.cache.RedisCacheManager;
import org.springframework.data.redis.connection.RedisConnectionFactory;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.data.redis.serializer.Jackson2JsonRedisSerializer;
@Configuration
@EnableCaching
public class RedisConfig extends CachingConfigurerSupport{
@Bean
public KeyGenerator keyGenerator() {
return new KeyGenerator() {
@Override
public Object generate(Object target, Method method, Object... params) {
StringBuilder sb = new StringBuilder();
sb.append(target.getClass().getName());
sb.append(method.getName());
for (Object obj : params) {
sb.append(obj.toString());
}
return sb.toString();
}
};
}
@SuppressWarnings("rawtypes")
@Bean
public CacheManager cacheManager(RedisTemplate redisTemplate) {
RedisCacheManager rcm = new RedisCacheManager(redisTemplate);
//设置缓存过期时间
//rcm.setDefaultExpiration();//秒
return rcm;
}
@Bean
public RedisTemplate<String, String> redisTemplate(RedisConnectionFactory factory) {
StringRedisTemplate template = new StringRedisTemplate(factory);
Jackson2JsonRedisSerializer jackson2JsonRedisSerializer = new Jackson2JsonRedisSerializer(Object.class);
ObjectMapper om = new ObjectMapper();
om.setVisibility(PropertyAccessor.ALL, JsonAutoDetect.Visibility.ANY);
om.enableDefaultTyping(ObjectMapper.DefaultTyping.NON_FINAL);
jackson2JsonRedisSerializer.setObjectMapper(om);
template.setValueSerializer(jackson2JsonRedisSerializer);
template.afterPropertiesSet();
return template;
}
}
RedisService
package www.ijava.com.service;
import java.io.Serializable;
import java.util.List;
import java.util.Set;
import java.util.concurrent.TimeUnit;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.*;
import org.springframework.stereotype.Service;
/
***/
@Service
public class RedisService {
@Autowired
private RedisTemplate redisTemplate;
/
** //操作字符串
* redisTemplate.opsForValue();
//操作hash
redisTemplate.opsForHash();
//操作
redisTemplate.opsForList();
//操作
list redisTemplate.opsForSet();
//操作有序set
set redisTemplate.opsForZSet();
*/
/
*** 写入缓存
* @param key
* @param value
* @return
*/
public boolean set(final String key, Object value) {
boolean result = false;
try {
ValueOperations<Serializable, Object> operations = redisTemplate.opsForValue();
operations.set(key, value);
result = true;
} catch (Exception e) {
e.printStackTrace();
}
return result;
}
/
*** 写入缓存设置时效时间
* @param key
* @param value
* @return
*/
public boolean set(final String key, Object value, Long expireTime) {
boolean result = false;
try {
ValueOperations<Serializable, Object> operations = redisTemplate.opsForValue();
operations.set(key, value);
redisTemplate.expire(key, expireTime, TimeUnit.SECONDS);
result = true;
} catch (Exception e) {
e.printStackTrace();
}
return result;
}
/
*** 批量删除对应的value
* @param keys
*/
public void remove(final String... keys) {
for (String key : keys) {
remove(key);
}
}
/
*** 批量删除key
* @param pattern
*/
public void removePattern(final String pattern) {
Set<Serializable> keys = redisTemplate.keys(pattern);
if (keys.size() > 0)
redisTemplate.delete(keys);
}
/
*** 删除对应的value
* @param key
*/
public void remove(final String key) {
if (exists(key)) {
redisTemplate.delete(key);
}
}
/
*** 判断缓存中是否有对应的value
* @param key
* @return
*/
public boolean exists(final String key) {
return redisTemplate.hasKey(key);
}
/
*** 读取缓存
* @param key
* @return
*/
public Object get(final String key) {
Object result = null;
ValueOperations<Serializable, Object> operations = redisTemplate.opsForValue();
result = operations.get(key);
return result;
}
/
*** 哈希 添加
* @param key
* @param hashKey
* @param value
*/
public void hmSet(String key, Object hashKey, Object value){
HashOperations<String, Object, Object> hash = redisTemplate.opsForHash();
hash.put(key,hashKey,value);
}
/
*** 哈希获取数据
* @param key
* @param hashKey
* @return
*/
public Object hmGet(String key, Object hashKey){
HashOperations<String, Object, Object> hash = redisTemplate.opsForHash();
return hash.get(key,hashKey);
}
/
*** 列表添加
* @param k
* @param v
*/
public void lPush(String k,Object v){
ListOperations<String, Object> list = redisTemplate.opsForList();
list.rightPush(k,v);
}
/
*** 列表获取
* @param k
* @param l
* @param l1
* @return
*/
public List<Object> lRange(String k, long l, long l1){
ListOperations<String, Object> list = redisTemplate.opsForList();
return list.range(k,l,l1);
}
/
*** 集合添加
* @param key
* @param value
*/
public void add(String key,Object value){
SetOperations<String, Object> set = redisTemplate.opsForSet();
set.add(key,value);
}
/
*** 集合获取
* @param key
* @return
*/
public Set<Object> setMembers(String key){
SetOperations<String, Object> set = redisTemplate.opsForSet();
return set.members(key);
}
/
*** 有序集合添加
* @param key
* @param value
* @param scoure
*/
public void zAdd(String key,Object value,double scoure){
ZSetOperations<String, Object> zset = redisTemplate.opsForZSet();
zset.add(key,value,scoure);
}
/
*** 有序集合获取
* @param key
* @param scoure
* @param scoure1
* @return
*/
public Set<Object> rangeByScore(String key,double scoure,double scoure1){
ZSetOperations<String, Object> zset = redisTemplate.opsForZSet();
return zset.rangeByScore(key, scoure, scoure1);
}
}
测试用的Controller
package www.ijava.com.controller;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RestController;
import www.ijava.com.service.RedisService;
@RestController
public class DemoController {
@Autowired
private RedisService redisService ;
@RequestMapping(value = "/test")
public String demoTest(){
boolean result = redisService.set("1","value");
Object object = redisService.get("1");
Object name = redisService.get("name");
System.out.println(object);
return result+"-------"+object+" ---"+name;
}
}
使用Redis-cli客户端查看
caffeine_redis二级缓存实现Spring接口
在项目优化阶段,发现缓存机制对提升性能至关重要。元源码尤其在数据更新主要由数据人员流程驱动,元源码而非频繁操作的元源码场景中,使用切面编程和自定义注解成为实现缓存的元源码合适方式。接下来,元源码libsonic源码解析我们将探讨如何实现通用型的元源码二级缓存,实现Spring接口规范。元源码
在研究过程中,元源码JSR/JCache缓存机制得到了解。元源码这些规范提供了一致的元源码缓存接口,让不同厂商的元源码实现兼容。Spring Cache抽象类层次结构图展示了这一整合机制。元源码
为了实现二级缓存,元源码我们基于Spring中的元源码`AbstractValueAdaptingCache`抽象接口,通过继承该接口来实现所需的缓存逻辑。该接口为缓存操作提供了基础封装,简化了实现过程。集成Redis等缓存解决方案时,`Cache`和`Redis`相关属性成为必要,通过`Properties`类实现配置的可扩展性和灵活性。
`lookup`方法在使用`@Cacheable`注解时执行,用于查询缓存数据。与之紧密相关的`put`方法则在更新数据或数据不存在于缓存中时调用,确保数据一致性。`evict`方法用于删除指定缓存数据,并通知其他节点进行同步更新。`clear`方法则负责清理所有缓存数据,同样触发节点间的货币系统源码数据同步。
在实际应用中,应考虑禁用`redis.keys`命令以避免安全风险,因此使用`scan`命令替代,确保数据安全性。`get`方法在使用缓存注解时不会直接调用,而是依赖父类的实现确保数据同步。
`CacheManager`类作为缓存管理器,负责初始化和维护缓存实例。在方法调用时,首先通过管理器获取缓存实例,确保操作的一致性和协调性。当数据发生变动时,通过`getCache`方法实现分布式缓存管理,确保数据的一致性。
测试环节中,构建了简单的Controller来验证`@Cacheable`、`@CachePut`、`@CacheEvict`和`@CacheClear`等注解在实际应用中的效果。通过集成测试,确保了缓存机制在不同场景下的正确性和高效性。
综上所述,通过合理设计和实现二级缓存机制,结合Spring接口规范和Redis等缓存解决方案,可以有效提升项目性能,实现数据的高效管理和一致性控制。在此过程中,充分考虑安全性和扩展性,确保系统在实际部署中的vue源码原码稳定性和可靠性。
SpringBoot2.0+整合redis,使用 RedisTemplate操作redis
整合 Redis 与 SpringBoot 2.0 需要关注 RedisTemplate 的使用,特别是在配置 cacheManager 时,SpringBoot 2.x 版本的 RedisCacheManager 构造方法存在差异,本文提供整理。在 Maven 引入 Redis 相关依赖和 Application.properties 配置 RedisConfig 时,需注意与 SpringBoot 2.x 版本的兼容性。
在配置 RedisCacheManager 时,重点在于其构造方法的变化,这要求在开发中进行相应的调整,确保与新版本的 SpringBoot 配合无误。同时,配置 cacheManager 是为了与注解配合使用 Redis,但在实际开发中,作者更倾向于使用 RedisTemplate,因为注解虽然简化了操作,但对复杂操作和异常处理的灵活性较低。对于习惯于直接控制代码逻辑的开发者而言,RedisTemplate 提供了更直接、灵活的控制方式。
以简单的 String 类型的 set 和 get 操作为例,展示如何使用 RedisTemplate 进行基本的 Redis 操作。这仅是 Redis 操作的冰山一角,对于其他数据类型的操作,后续可以撰写专门的文章进行详细探讨。
本文内容已提交至 GitHub,地址为:github.com/NeoChenDev/N... 文中代码部分参考了其他博主的分享,感谢他们的贡献。如有任何侵权行为,前锋狙击源码请联系本人。
RedisCacheManager设置Value序列化器技巧
配置CacheManager时,需参考博文:springboot2.0 redis EnableCaching的配置和使用。RedisCacheManager构造函数需提供RedisOperations实例,即RedisTemplate。在创建缓存时,通过RedisCache构造函数传入redisOperations。
采用全局通用的序列化器GenericJackson2JsonRedisSerializer,调试发现序列化内容加入对象的类型信息。此序列化器通过Jackson的ObjectMapper实现序列化与反序列化,开启默认类型配置。使用Protostuff自定义序列化与反序列化工具,测试结果显示同样加入对象类型信息。JdkSerializationRedisSerializer内部使用ObjectInputStream与ObjectOutputStream完成序列转换与反序列化,发现序列化内容同样加入类型信息。若要缓存的Java对象需实现Serializable接口,否则将引发特定错误。
当设置Jackson2JsonRedisSerializer,内部序列化过程通过Jackson ObjectMapper完成,不包含对象类型信息。使用此序列化器时需指定缓存对象类型。通过实现不同RedisCache对应不同RedisTemplate(即不同序列化器)的策略,实现自定义RedisCacheManager。RedisCacheManager通过加载自定义配置实现类RedisCacheConfigurationProvider获取不同RedisCache的配置。自定义RedisCache配置提供者抽象类,根据不同的缓存类型设置不同序列化器,允许用户根据缓存名称设置不同存储类型。
复合CacheManager通过实现给定的ocal 源码分析委托CacheManager实例集合,配置多个CacheManager,每个CacheManager可配置不同序列化器。注意,如果复合管理器委托的常规CacheManagers在请求时回退到命名缓存的延迟创建,需确保它们能处理未知缓存名称的情况,或在请求时自动创建缓存区域。通过这种方式,可以灵活配置不同缓存的序列化策略。
基于Spring Cache实现二级缓存(Caffeine+Redis)
在探索缓存优化之道时,硬编码使用缓存的方式显得不够优雅。面对查询效率的提升需求,我们通常会采用缓存策略。然而,这种方式在业务逻辑与缓存操作之间引入了不必要的耦合,导致代码的复杂性和维护成本上升。Spring Cache的引入,为这一问题提供了优雅的解决方案。
Spring Cache是Spring-context包提供的组件,允许通过注解方式使用缓存。它定义了标准接口,如Cache和CacheManager,使得缓存的管理与业务逻辑分离,提高代码的可读性和可维护性。
Spring Cache的核心接口包括Cache和CacheManager。Cache接口定义了缓存的基本操作,如存储、读取和清理;CacheManager接口则负责创建Cache实现bean,并提供基于缓存名进行隔离的功能。
在Spring Cache中,常用注解有@Cacheable、@CacheEvict、@CachePut和@Caching。@Cacheable用于查询数据的方法,@CacheEvict用于清除缓存,@CachePut用于更新缓存,而@Caching则允许在一个方法上配置多种注解。
为了进一步提升性能,我们引入了二级缓存的概念。一级缓存通常位于应用内部,如使用Caffeine作为高速缓存,而二级缓存则利用像Redis这样的远程存储。这种设计通过减少对远程缓存的频繁访问,显著降低了网络开销。
实现二级缓存时,需要考虑一致性、空值存储、缓存预热、存储数量上限、过期策略等关键问题。Caffeine作为高性能缓存库,提供了一种简洁的解决方案。它支持手动、同步加载和异步加载的写入策略,以及基于大小、时间或引用的缓存值清理策略。
统计信息的记录、高效的缓存淘汰算法、底层数据存储采用ConcurrentHashMap(结合了JDK8的优化)都是Caffeine的关键特性。LRU、LFU和FIFO等算法被用于缓存淘汰,其中W-TinyLFU算法结合了LRU和LFU的优点,以实现高命中率和低内存占用。
在实际应用中,结合Spring Cache与Caffeine实现二级缓存时,还需考虑分布式节点的一致性问题。通过Redis的订阅/发布功能,可以实现对数据更新和删除操作的跨节点通知,从而确保缓存的一致性。引入Redis缓存,不仅简化了节点间通信的复杂性,还避免了依赖额外组件。
为了集成Caffeine缓存,可通过Maven引入相关依赖包,并在配置文件(如application.yml)中添加二级缓存相关配置。在启动类上使用@EnableCaching注解启用缓存功能,最后在需要缓存的方法上添加@Cacheable注解即可。
SpringBoot的Cacheable缓存注解
为了提升应用程序的性能,我们在处理大量数据读取和写入操作时,往往会采用缓存技术。Spring Boot 提供了一套高效便捷的缓存解决方案,支持将数据缓存至 Redis 中。
在 Spring Boot 中,我们只需在方法上添加相应的注解即可实现缓存功能。
首先,您需要在项目中引入 Redis 依赖。以下是在 pom.xml 中添加 Redis 依赖的示例:
引入 Redis 依赖后,接下来需要配置 Redis 相关信息。以下是一个 Redis 配置的示例:
在此配置中,host 和 port 属性分别指定了 Redis 服务器的主机名和端口号,password 属性用于指定 Redis 服务器的密码(如果有的话),而 database 属性则指定了 Redis 服务器使用的数据库编号。
Redis 默认序列化器为 JdkSerializationRedisSerializer,但通常我们更倾向于使用 StringRedisSerializer 或 Jackson2JsonRedisSerializer 将缓存值序列化为字符串或 JSON 格式。以下是一个自定义序列化器的示例配置:
在这个示例中,我们通过自定义 Bean 配置了 RedisTemplate,使用 StringRedisSerializer 序列化 Redis 键,并使用 Jackson2JsonRedisSerializer 序列化 Redis 值为 JSON 格式。
使用 Cacheable 注解来标记需要进行缓存的方法。以下是一个带有 Cacheable 注解的示例方法:
在这个例子中,@Cacheable 注解用于标记 getUserById 方法,value 属性用于指定缓存的存储区域名称。由于我们正在使用 Redis 作为缓存,因此 Redis 中的 key 将由 Cacheable 注解中的 key 属性指定。在此示例中,key 属性设置为 "#id",这意味着我们将使用方法参数 id 作为 Redis 缓存的键。
在某些情况下,我们需要以多个参数作为 key 来缓存数据。此时,我们可以使用表达式语言(SpEL)来设置多个参数,如下所示:
在这个示例中,我们使用了表达式语言(SpEL)将 id 和 name 两个参数组合成了一个 Redis 缓存键。
缓存的有效期对缓存的性能和可靠性有很大影响。可以使用 @Cacheable 注解上的 expire 属性来设置缓存的过期时间。以下是一个设置缓存时效的示例:
在此示例中,我们添加了名为 expire 的属性,该属性用于指定缓存的过期时间(以秒为单位)。在此示例中,我们设置了缓存过期时间为 秒,即 分钟。
有时候,我们需要清除 Redis 缓存中的某些数据,以便在下一次访问时重建缓存。在 Spring Boot 中,可以使用 @CacheEvict 注解来清除 Redis 缓存中的数据。以下是一个使用 @CacheEvict 注解的示例:
在这个例子中,我们添加了删除单个用户和删除所有用户的方法,使用 @CacheEvict 注解来删除 Redis 缓存中的相应数据。请注意,我们设置了 allEntries 属性为 true,以删除所有缓存中的数据。
有时候,我们需要在特定条件下才进行缓存操作。例如,只有当用户年龄大于 岁时才进行缓存。在 Spring Boot 中,可以使用 @Cacheable、@CachePut 和 @CacheEvict 注解上的 condition 属性来设置缓存条件。以下是一个使用 condition 属性的示例:
在这个例子中,我们添加了一个名为 condition 的属性,该属性用于指定缓存的条件。在此示例中,我们将 condition 属性设置为 "#age > ",这意味着只有当 age 大于 时,才进行缓存操作。
在实际使用中,应用程序缓存数据的管理也是非常重要的。Spring Boot 提供了一个名为 CacheManager 的接口,您可以使用它来创建并管理缓存对象。以下是一个使用 CacheManager 的示例:
在这个示例中,我们创建了一个名为 CacheConfig 的配置类,并使用 @EnableCaching 注解来开启缓存支持。然后,我们通过实现 CachingConfigurerSupport 接口,覆盖 cacheManager 方法,创建了一个 RedisCacheManager 对象,并将其返回。在此 RedisCacheManager 中,我们使用默认的 RedisCacheConfiguration 进行了一些配置,例如设置缓存的过期时间,同时指定了 Redis 的连接信息。
本文介绍了如何在 Spring Boot 应用程序中使用 Redis 进行缓存,包括配置 RedisTemplate、使用 Cacheable 注解、设置缓存有效期、使用 @CacheEvict 清除缓存数据以及使用 CacheManager 管理缓存等。