目标:简化缓存代码的编写
解决方案:基于AOP(面向切面编程)方式实现缓存应用
实践步骤:
第一步:在启动上类添加@EnableCaching注解(开启AOP方式的缓存配置),例如:
@EnableCaching //启动AOP方式的缓存配置
@EnableCaching //启动AOP方式的缓存配置
@SpringBootApplication
public class RedisApplication {
public static void main(String[] args) {
SpringApplication.run(RedisApplication.class,args);
}
// @Bean
// @ConditionalOnMissingBean(
// name = {"redisTemplate"}
// )
// public RedisTemplate<Object, ? extends Object> redisTemplate(RedisConnectionFactory redisConnectionFactory) throws UnknownHostException {
// RedisTemplate<Object, ? extends Object> template = new RedisTemplate();
// template.setConnectionFactory(redisConnectionFactory);
// return template;
// }
}
第二步:重构TagServiceImpl中的selectTags()方法,方法上使用@Cacheable注解,例如:
@Service
public class TagServiceImpl implements TagService{
@Autowired
private TagMapper tagMapper;
@Autowired
private RedisTemplate redisTemplate;
@Cacheable(value = "tagCache")//基于此注解描述的方法为缓存切入点
//@Cacheable使用此方法 系统底层会先从缓冲查找数据 假如没有缓冲,会查询mysql--配置了redis所以存到redis
//这个注解要生效 需要在启动类加上@EnableCaching
@Override
public List<Tag> selectTags(){
return tagMapper.selectList(null);
}
// @Override
// public List<Tag> selectTags() {
// System.out.println("service select tags");
// //从redis中查询Tag信息 redis有就直接返回
// ValueOperations<String,List> valueOperations =
// redisTemplate.opsForValue();
// List<Tag> tags = valueOperations.get("tags");
// System.out.println("tags="+tags);
//
//
// if(tags!=null&&!tags.isEmpty())
// return tags;
//
//
// //从redis中没有获取tag信息,查询mysql
// System.out.println("select from mysql");
// tags = tagMapper.selectList(null);
//
// //将从mysql中查询的信息存储到redis
// valueOperations.set("tags", tags);
// //返回查询结果
//
// return tags;
//
// }
}
其中,@Cacheable描述的方法为AOP中的一个切入点方法,访问这个方法时,系统底层会通过一个拦截器,检查缓存中是否有你要的数据,假如有则直接返回,没有则执行方法从数据库查询数据.
在redis的查询结果:
RedisTemplate 默认jdk序列化
想要修改序列化模式:要重新配置:
@Bean
public RedisCacheManager cacheManager(
RedisConnectionFactory connectionFactory){
RedisCacheConfiguration config=
RedisCacheConfiguration.defaultCacheConfig()
//配置key序列化
.serializeKeysWith(RedisSerializationContext.
SerializationPair.fromSerializer(new StringRedisSerializer()))
//配置value的序列化
.serializeValuesWith(RedisSerializationContext.
SerializationPair.fromSerializer(new Jackson2JsonRedisSerializer<Object>(
Object.class)));
return RedisCacheManager
.builder(connectionFactory)
.cacheDefaults(config)//修改默认配置
.transactionAware() //启动默认事务
.build();
}
更改后:
缓存数据一致性的问题:
当从数据库查询数据以后,假如将数据库存入到缓存,后续更新可数据库的数据,假如没有更新缓存就会出现缓存数据与数据库数据不一致这样的现象,对于这样的问题,有时是允许出现的
缓冲
最终一致性