主频 集成电路 总线 内存 控制器 运算器
主页 缓存 正文

基于Redis的缓存策略应用解析

SpringCache整合Redis做缓存使用~快速上手~

SpringCache通过集成Redis作为缓存工具来简化缓存管理。
它是通过注解实现的,有优点也有缺点。
为了快速上手并使用SpringBoot,首先要进行常规的前期准备工作,例如引入SpringCache集成Redis依赖、配置相关配置文件和Redis配置等。
它直接应用于控制器、服务和映射器层之间,并且允许您在数据从服务层返回时缓存数据(如果您需要测试它)。
作为参考,这里有两种清除缓存的方法。
一种是擦除整个分区,另一种是针对特定键。
SpringCache注解要求方法是public的,@Cacheable用于缓存方法返回值,@CachePut用于更新缓存,@CacheEvict用于驱逐缓存。
@Caching提供了一组可以同时操作多个缓存的注解,@CacheConfig用于类级别的缓存配置,解决重复注解的问题。
需要记住的事情包括避免缓存分页查询结果、处理基于代理的AOP问题、确保@Cache注解的方法是公共的,以及理解@CacheEvict在发生异常时默认不会清除缓存。
深入理解这些特点还需要更多的实践和探索。

人人都要知道的,Redis缓存使用的三种模式

缓存技术在互联网应用中发挥着重要作用,其目的是提高系统性能和稳定性。
Redis作为高性能缓存数据库,广泛应用于各种互联网场景。
本文重点介绍Redis缓存使用的三种模式:CacheAside(缓存旁路)、Read/Write(读写黑客)、WriteBehindCaching(异步缓存写入),并分析它们的特点和适用场景。
CacheAsideCacheAside模式是最直接的缓存方法。
应用程序首先尝试从缓存中读取数据,如果不存在,则从数据库中获取并临时存储。
更新过程中,先更新数据库,然后清除缓存。
该模式实现简单,缓存与数据库之间数据一致性好,适合读多写少、数据一致性要求不高的场景。
读/写/读/写模式通过中间层管理缓存与数据库的交互,提高并发性和扩展性。
应用程序通过中间层对缓存和数据库进行读写,保证数据的一致性。
适用于读写操作较多、数据一致性要求较高的场景。
WriteBehindCachingWriteBehindCaching模式先将操作记录在缓存中,然后异步更新数据库,有效提高写入性能,减轻数据库负担。
但要注意数据一致性问题。
该模式适用于写多读少、数据一致性要求不高的场景。
总结:Redis缓存模式的选择要根据具体的业务场景和需求而定。
CacheAside模式操作简单,适用于读写量大、数据一致性要求不高的情况;读写模式通过中间层将缓存和数据库分开,适用于需要大量读写、对数据一致性要求较高的情况。
场景:WriteBehindCaching模式通过异步写入提高写操作的性能,并且方便针对写多读少、数据一致性要求不高的场景。
在实际应用中,合理选择缓存模式可以极大地提高系统性能和稳定性。

SpringBoot整合Redis做缓存-自定义缓存序列化方式,防止缓存数据乱码问题

首先,添加依赖项:

org.springframework.bootspring-boot-starter-data-redis${spring-boot.version}org.springframework.bootspring-boot-starter-cache${spring-boot.version}

我这里使用的SpringBoot版本是:2.2.5。
RELEASE

jedis和lettuce的区别

1.Jedis:

在实现上,它是直接连接到Redisserver的,不是多线程环境,除非使用连接池为每个redis实例添加物理连接。

2.Lettuce:

它是一个可扩展、安全且完全非阻塞的Redis客户端,多个线程可以共享一个RedisConnection。
它使用NettyNIO框架有效地管理多个连接,提供异步和同步数据访问以创建非阻塞交互式应用程序。

我的项目这里的配置文件使用的是Lettuce。
配置文件:

spring:datasource:url:jdbc:mysql://192.168.104.64:3306/spring_boot_plus?serverTimezone=Asia/Shanghai&useUnicode=true&characterEncoding=utf8&useSSL=false&allowPublicKeyRetrieval=trueusername:rootpassword:huauN2021#Redis配置redis:database:0host:192.168.104.102password:huauN@2021port:6379timeout:6000#连接超时时长(毫秒)lettuce:pool:max-active:1024#最大数量连接数连接池中(默认为8,-1表示无限制,如果池分配超过max_active的jedis实例,此时池将被耗尽)max-wait:10000#连接的最大等待时间,默认值以毫秒为单位-1,表示超时时不会抛出JedisConnectionExceptionmax-idle:10min-idle:5

首先查找redis配置类,如果没有有超时,有新的配置类:

packagegc.cnnvd.config;importcom.fasterxml.jackson.annotation.JsonAutoDetect;importcom.fasterxml.jackson.annotation.PropertyAccessor;importcom.fasterxml.jackson.databind.ObjectMapper;导入org.springframework.context.annotation.Bean;导入org.springframework.context.annotation.Configuration;导入org.springframework.data.redis.connection.RedisConnectionFactory;importorg.springframework.data.redis.core.RedisTemplate;importorg.springframework.data.redis.serializer.Jackson2JsonRedisSerializer;importorg.springframework.data.redis.serializer.StringRedisSerializer;/***

*配置RedisTemplate*

**@authorlinmengmeng*@date2021-07-21*/@ConfigurationpublicclassRedisTemplateConfig{/***redisTemplate的配置*@paramfactory*@return***自定义RedisTemplate原因:*1.将public方法修改为,避免繁琐的类型转换。
*2.将值序列化方法更改为Jackson2JsonRedisSerializer,因为底层RedisSerializer不会将带双引号的值序列化为字符串类型,并且会自动添加双引号。
**/@Bean@Suppre ssWarnings("all")publicRedisTemplateredisTemplate(RedisConnectionFactoryfactory){RedisTemplateredisTemplate=newRedisTemplate();redisTemplate.setConnectionFactory(factory);Jackso//定义类型Sequentialinput该类必须是non类型final,否则会报错Mapper.enableDefaultTyping(ObjectMapper.DefaultTyping.NON_FINAL);jackson2JsonRedisSerializer.setObjectMapper(mapper);StringRedisSerializerstringRedisSerializer=newStringRedisSerializer();//设置key使用字符串序列化方式redisTemplate.setKeySerializer(stringRedisSerializer);//使用字符串序列化方法设置hashkeyredisTemplate.setHashKeySerializer(stringRedisSerializer);//使用jackson2序列化方法设置值redisTemplate.setValueSerializer(jackson2JsonRedisSerializer);//设置hash值取决于jackson2的序列化方法redisTemplate.setHashValueSerializer(jackson2JsonRedisSerializer);redisTemplate.afterPropertiesSet();returnredisTemplate;}

如果之前配置过redisTemplate,再次启动配置文件时会提示异常,提示redisTemplatebean创建失败,或者已经存在或者像那样的东西。

然后是RedisCacheConfig:

packagegc.cnnvd.config;importorg.springframework.cache.CacheManager;importorg.springframework.cache.annotation.CachingConfigurerSupport;importorg.springframework.cache.annotation.EnableCaching;importorg.springframework.cache.interceptor.KeyGenerator;importorg.springframework.context.annotation.Bean;importorg.springframework.context.annotation.Configuration;importorg.springframework.data.redis.cache.RedisCacheConfiguration;导入org.springframework.data.redis.cache.RedisCacheManager;导入org.springframework.data.redis.connection.RedisConnectionFactory;导入org.springframework.data.redis.serializer.Jackson2JsonRedisSerializer;importorg.springframework.data.redis.serializer.RedisSerializationContext;importorg.springframework.data.redis.serializer.RedisSerializer;importorg.springFramework.data.redis.serializer.StringRedisSerializer;importjava.time.Duration;importjava.util.Arrays;/***

*RedisCache配置*

*@authorgeekidea*@date2018-11-08*/@config@EnableCachingpublicclassRedisCacheConfigextendsCachingConfigurerSupport{@Bean@OverridepublicKeyGeneratorkeyGenerator(){return(目标、方法、参数)->{StringBufferredisKey=newStringBuffer();redisKey.append(target.getClass().getName())。
追加(“-”);redisKey.append(method.getName());if(params.length>0){redisKey.append(“-”).append(Arrays.deepToString(params));}returnredisKey.toString();};}/***配置redis缓存*修改序列化方法,解决乱码缓存代码*@paramfactory*@return*/@BeanpublicCacheManagerrcacheManager(RedisConnectionFactoryfactory){RedisSerializerredisSerializer=newStringRedisSerializer();Jackson2JsonRedisSerializerjackson2JsonRedisSerializer=newJackson2JsonRedisSerializer(Object.class);//序列化器配置RedisCacheConfigurationconfig=RedisCacheConfiguration.defaultCacheConfig();RedisCacheConfigurationredisCacheConfiguration=config//Key序列化方法redisSerializer.serializeKeysWith(RedisSerializationContext.SerializationPair.fromSerializer(redisSerializer))//Value序列化方法jackson2JsonRedisSerializer.serializeValuesWith(RedisSerializationContext.SerializationPair.fromSerializer(jackson2JsonRedisSerializer))//设置pre fix//.pre fixKeysWith("project:")//设置过期时间.entryTtl(Duration.ofSeconds(60*60));RedisCacheManagerrcacheManager=RedisCacheManager.builder(factory).cacheDefaults(redisCacheConfiguration).build();returncacheManager;}

我已将@EnableScheduling注释直接添加到此处的配置文件中。
如果这里不添加,可以直接在启动类中添加注解:@EnableScheduling

无论找到什么服务方法进行测试:

@Override@Cacheable(value="adminUser",key="#adminUserDetailParam获取我。
d()",除非="#result==null")publicAdminUserDetailVOgetAdminUserDetail(AdminUserDetailParamadminUserDetailParam){AdminUserMergeradminUserMerger=adminUserMapper.selectAdminUserDetail(adminUserDetailParam.getId(),adminUserDetailParam.getVersion());log.info("------------转到数据库查询-------------");if(adminUserMerger==null){thrownewBusinessException("未找到用户信息");}AdminUserDetailVOadminUserDetailVO=newAdminUserDetailVO();BeanCopierUtils.copyProperties(adminUserMerger,adminUserDetailVO);returnadminUserDetailVO;

这里只有一行注解@Cacheable(value="adminUser",key="#adminUserDetailParam.getId()",unless="#result==null"),其中值是键前缀redis,导入com.alibaba.fastjson.JSONObject;导入gc.cnnvd.system.adminuser.param.AdminUserDetailParam;导入gc.cnnvd.system.adminuser.service.AdminUserService;导入gc.cnnvd.system。
管理员用户.vo.AdminUserDetailVO;importgc.cnnvd.test.BaseTest;importorg.junit.Test;importorg.springframework.beans.factory.annotation.Autowired;/***@Autherlinmengmeng*@Date2021-07-2019:15*/publicclassQueryTestextendsBaseTest{@AutowiredprivateAdminUserServiceadminUserService;@TestpublicvoidtestGetAdminDetail(){AdminUserDetailParamadminUserDetailParam=newAdminUserDetailParam();adminUserDetailParam.setId("test001");adminUserDetailParam.setVersion(0);AdminUserDetailVOadminUserDetail=adminUserService.getAdminUserDetail(adminUserDetailParam);System.out.println(JSONObject.toJSONString(adminUserDetail));}

写完测试用例后,发现缓存第一次运行良好,执行了数据库查询。
第二次,直接进入redis缓存。

缓存,使用可视化工具显示如下图:

作者:linmengmeng

热门资讯
总线分为哪三种
解析中断类型码与向量表之间的内在联系
半导体集成电路和芯片的区别
简约设计探索简洁UI的魅力
深入解析Profibus总线协议工业自动化领域的通信标准
redis清空缓存命令
最基本的门电路是哪三个
如何把手机里的缓存彻底清除