缓存作用:
举个例子:在我们程序中,很多配置数据(例如一个商品信息、一个白名单、一个第三方客户的回调接口),这些数据存在我们的DB上,数据量比较少,但是程序访问很频繁,这种情况下,将数据放一份到我们的内存缓存中将大大提升我们系统的访问效率,因为减少了数据库访问,有可能减少了数据库建连时间、网络数据传输时间、数据库磁盘寻址时间……
总的来说,涉及查询场景都可以考虑使用缓存优化性能:1、查数据库2、读取文件3、网络访问,特别是调用第三方服务查询接口!
注意:并不是缓存设计的多,性能就一定好,对更新频繁的数据,不推荐缓存,保证数据一致性是缓存的前提!
一致性解释:缓存数据和数据库数据一致,避免脏(错误)数据!
第一步:添加相关依赖
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-cache</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-redis</artifactId>
</dependency>
<dependency>
<groupId>redis.clients</groupId>
<artifactId>jedis</artifactId>
</dependency>
第二步:在公共模块的resources目录中添加application-cache .yml
spring:
cache:
type: redis
redis:
host: 1.15.122.194
port: 6379
jedis:
pool:
max-wait: 2000ms
min-idle: 2
max-idle: 8
max-active: 10
第三步:编写缓存配置类(这个只是单纯的配置类,并没有使用@Configuration注解生效,需要其他配置类集成它,添加@Configuration注解才可以生效生效)
public class CacheConfiguration {
@Bean
@Primary
public RedisCacheManager cacheManagerHour(RedisConnectionFactory redisConnectionFactory){
RedisCacheConfiguration instanceConfig = instanceConfig(1 * 3600L);
return RedisCacheManager.builder(redisConnectionFactory)
.cacheDefaults(instanceConfig)
.transactionAware()
.build();
}
@Bean
public RedisCacheManager cacheManagerDay(RedisConnectionFactory redisConnectionFactory){
RedisCacheConfiguration instanceConfig = instanceConfig(24 * 3600L);
return RedisCacheManager.builder(redisConnectionFactory)
.cacheDefaults(instanceConfig)
.transactionAware()
.build();
}
private RedisCacheConfiguration instanceConfig(Long ttl){
Jackson2JsonRedisSerializer<Object> jackson2JsonRedisSerializer
= new Jackson2JsonRedisSerializer<Object>(Object.class);
ObjectMapper objectMapper = new ObjectMapper();
objectMapper.disable(SerializationFeature.WRITE_DATES_AS_TIMESTAMPS);
objectMapper.registerModule(new JavaTimeModule());
objectMapper.configure(MapperFeature.USE_ANNOTATIONS,false);
objectMapper.setSerializationInclusion(JsonInclude.Include.NON_NULL);
objectMapper.activateDefaultTyping(LaissezFaireSubTypeValidator.instance,
ObjectMapper.DefaultTyping.NON_FINAL, JsonTypeInfo.As.PROPERTY);
jackson2JsonRedisSerializer.setObjectMapper(objectMapper);
return RedisCacheConfiguration.defaultCacheConfig()
.entryTtl(Duration.ofSeconds(ttl))
.disableCachingNullValues()
.serializeValuesWith(RedisSerializationContext.SerializationPair.fromSerializer(jackson2JsonRedisSerializer));
}
}
第四步:在服务消费者pom.xml中添加公共模块依赖,以此来使用缓存
<dependency>
<artifactId>store-commons</artifactId>
<groupId>com.xin</groupId>
<version>1.0-SNAPSHOT</version>
</dependency>
第五步:在application.yml文件中激活缓存
spring:
datasource:
url: jdbc:mysql://localhost:3306/store_admin?useSSL=false
username: root
password: root
driver-class-name: com.mysql.jdbc.Driver
type: com.alibaba.druid.pool.DruidDataSource
profiles:
active: cache,mq
thymeleaf:
cache: true
check-template: true
check-template-location: true
servlet:
content-type: text/html
enabled: true
encoding: UTF-8
mybatis-plus:
mapper-locations: classpath:mappers/*.xml
configuration:
map-underscore-to-camel-case: true
auto-mapping-behavior: full
lazy-loading-enabled: true
aggressive-lazy-loading: false
type-aliases-package: com.xin.pojo
ribbon:
ReadTimeout: 60000
ConnectTimeout: 60000
eager-load:
enabled: true
clients:
- admin-service
feign:
httpclient:
enabled: true
max-connections: 200
max-connections-per-route: 50
client:
default:
ConnectTimeOut: 10000
ReadTimeOut: 10000
server:
servlet:
context-path: /admin
aliyun:
oss:
file:
endpoint: oss-cn-beijing.aliyuncs.com
keyid: LTAI5t82cN3TfofxJywKvoj5
keysecret: 7cPhJQBMNewuqXXnUiEjpj1l8YeONo
bucketname: store-b2c
第六步:在启动类上添加@EnableCaching,开启缓存
第七步:创建配置类,集成公共模块中的CacheConfiguration缓存配置类
第八步:在service层中使用缓存
SpringBoot实现Redis缓存(SpringCache+Redis的整合)
补充:
@Cacheable
位置:添加到方法和类上
作用:调用方法,查询是否有缓存,有直接走缓存,没有走方法,将方法的返回值进行缓存!
参数:
value = String{} 配置缓存的 配置缓存‘分区’,相当于缓存的标示!
key = String 配置缓存的 ‘分区’下的具体表示,此处支持SpringEL表达式,动态命名
cacheManager = String 选择配置类中的缓存配置对象beanname,不选走默认!
condition = String 注解生效条件, 支持SpringEl表达式 例如: "#result != null"
结果不为null,进行缓存!
例如:
@Cacheable(value = "product",key = "#root.methodName+" +
"'-'+#productParamInteger.categoryID+" +
"'-'+#productParamInteger.currentPage+" +
"'-'+#productParamInteger.pageSize",cacheManager = "cacheManagerbean")
SpringEL表达式简单了解:
#开头
#root.method 被调用的方法
#root.methodName 被调用的方法名称
#root.target 调用方法的对象
#root.args 方法的参数对象数组 支持[index]获取具体参数
#result 方法执行后的结果
#形参名 直接获取行参数名称 支持ognl向下继续读取
注意:
缓存也分为curd
所以,设计缓存value和key的时候,多思考,后期还需要进行删除和替换动作!
@CachePut
位置:添加到方法和类上
作用:不影响方法使用,将方法的返回值,进行指定的key更新,通常添加到修改方法上!
参数:
value = String{} 配置缓存的 配置缓存‘分区’,相当于缓存的标示!
key = String 配置缓存的 ‘分区’下的具体表示,此处支持SpringEL表达式,动态命名
cacheManager = String 选择配置类中的缓存配置对象beanname,不选走默认!
condition = String 注解生效条件, 支持SpringEl表达式 例如: "#result != null"
结果不为null,进行更新!
例如:
@CachePut(key = "#id", condition = "#result != null"),
@CacheEvict
位置:添加到方法和类上
作用:不影响方法使用,将方法的返回值,进行指定的key失效,通常添加到删除方法上!
参数:
value = String{} 配置缓存的 配置缓存‘分区’,相当于缓存的标示!
key = String 配置缓存的 ‘分区’下的具体表示,此处支持SpringEL表达式,动态命名
cacheManager = String 选择配置类中的缓存配置对象beanname,不选走默认!
condition = String 注解生效条件, 支持SpringEl表达式 例如: "#result != null"
结果不为null,进行失效!
例如:
@CacheEvict(value = "student", key = "'saveCache01'")
@CacheEvict(value = "list.product",allEntries = true)
@Caching(evict = {
@CacheEvict(value = "student", key = "'saveCache01'"),
@CacheEvict(value = "student", key = "'saveCache02'")
})
@Caching
位置:添加方法和类上
作用:多包涵注解,可以包含上面三个注解,用于复杂的缓存策略!
参数:
Cacheable [] cacheable 配置多个缓存
CachePut [] put 配置多个更新
CacheEvict [] evict() 配置多个缓存
例如:
订单模块
订单支付,需要更新订单缓存,还要清空热门商品缓存!
|