Spring思维导图,让Spring不再难懂(cache篇)


声明:本文转载自https://my.oschina.net/u/3080373/blog/1524728,转载目的在于传递更多信息,仅供学习交流之用。如有侵权行为,请联系我,我会及时删除。

关于缓存

缓存是实际工作中非常常用的一种提高性能的方法。而在java中,所谓缓存,就是将程序或系统经常要调用的对象存在内存中,再次调用时可以快速从内存中获取对象,不必再去创建新的重复的实例。这样做可以减少系统开销,提高系统效率。

在增删改查中,数据库查询占据了数据库操作的80%以上,而非常频繁的磁盘I/O读取操作,会导致数据库性能极度低下。而数据库的重要性就不言而喻了:

  • 数据库通常是企业应用系统最核心的部分
  • 数据库保存的数据量通常非常庞大
  • 数据库查询操作通常很频繁,有时还很复杂

在系统架构的不同层级之间,为了加快访问速度,都可以存在缓存

缓存不同层级的作用.png

spring cache特性与缺憾

现在市场上主流的缓存框架有ehcache、redis、memcached。spring cache可以通过简单的配置就可以搭配使用起来。其中使用注解方式是最简单的。

特性与缺憾.png

Cache注解

缓存注解.png

从以上的注解中可以看出,虽然使用注解的确方便,但是缺少灵活的缓存策略,

缓存策略:

  • TTL(Time To Live ) 存活期,即从缓存中创建时间点开始直到它到期的一个时间段(不管在这个时间段内有没有访问都将过期)

  • TTI(Time To Idle) 空闲期,即一个数据多久没被访问将从缓存中移除的时间

项目中可能有很多缓存的TTL不相同,这时候就需要编码式使用编写缓存。

条件缓存

根据运行流程,如下@Cacheable将在执行方法之前( #result还拿不到返回值)判断condition,如果返回true,则查缓存; 

@Cacheable(value = "user", key = "#id", condition = "#id lt 10")   public User conditionFindById(final Long id)   

如下@CachePut将在执行完方法后(#result就能拿到返回值了)判断condition,如果返回true,则放入缓存

@CachePut(value = "user", key = "#id", condition = "#result.username ne 'zhang'")   public User conditionSave(final User user)    

  如下@CachePut将在执行完方法后(#result就能拿到返回值了)判断unless,如果返回false,则放入缓存;(即跟condition相反)

@CachePut(value = "user", key = "#user.id", unless = "#result.username eq 'zhang'")   public User conditionSave2(final User user)    

  如下@CacheEvict, beforeInvocation=false表示在方法执行之后调用(#result能拿到返回值了);且判断condition,如果返回true,则移除缓存;

@CacheEvict(value = "user", key = "#user.id", beforeInvocation = false, condition = "#result.username ne 'zhang'")  public User conditionDelete(final User user)    
  • 小试牛刀,综合运用:
    @CachePut(value = "user", key = "#user.id")     public User save(User user) {         users.add(user);         return user;     }      @CachePut(value = "user", key = "#user.id")     public User update(User user) {         users.remove(user);         users.add(user);         return user;     }      @CacheEvict(value = "user", key = "#user.id")     public User delete(User user) {         users.remove(user);         return user;     }      @CacheEvict(value = "user", allEntries = true)     public void deleteAll() {         users.clear();     }      @Cacheable(value = "user", key = "#id")     public User findById(final Long id) {         System.out.println("cache miss, invoke find by id, id:" + id);         for (User user : users) {             if (user.getId().equals(id)) {                 return user;             }         }         return null;     } 

配置ehcache与redis

  • spring cache集成ehcache,spring-ehcache.xml主要内容:
<dependency> 	<groupId>net.sf.ehcache</groupId> 	<artifactId>ehcache-core</artifactId> 	<version>${ehcache.version}</version> </dependency> 
<!-- Spring提供的基于的Ehcache实现的缓存管理器 -->      <!-- 如果有多个ehcacheManager要在bean加上p:shared="true" --> <bean id="ehcacheManager" class="org.springframework.cache.ehcache.EhCacheManagerFactoryBean">      <property name="configLocation" value="classpath:xml/ehcache.xml"/> </bean>      <bean id="cacheManager" class="org.springframework.cache.ehcache.EhCacheCacheManager">      <property name="cacheManager" ref="ehcacheManager"/>      <property name="transactionAware" value="true"/> </bean>      <!-- cache注解,和spring-redis.xml中的只能使用一个 --> <cache:annotation-driven cache-manager="cacheManager" proxy-target-class="true"/> 
  • spring cache集成redis,spring-redis.xml主要内容:
<dependency> 	<groupId>org.springframework.data</groupId> 	<artifactId>spring-data-redis</artifactId> 	<version>1.8.1.RELEASE</version> </dependency> <dependency> 	<groupId>org.apache.commons</groupId> 	<artifactId>commons-pool2</artifactId> 	<version>2.4.2</version> </dependency> <dependency> 	<groupId>redis.clients</groupId> 	<artifactId>jedis</artifactId> 	<version>2.9.0</version> </dependency> 
<!-- 注意需要添加Spring Data Redis等jar包 --> <description>redis配置</description>  <bean id="jedisPoolConfig" class="redis.clients.jedis.JedisPoolConfig"> 	<property name="maxIdle" value="${redis.pool.maxIdle}"/> 	<property name="maxTotal" value="${redis.pool.maxActive}"/> 	<property name="maxWaitMillis" value="${redis.pool.maxWait}"/> 	<property name="testOnBorrow" value="${redis.pool.testOnBorrow}"/> 	<property name="testOnReturn" value="${redis.pool.testOnReturn}"/> </bean>  <!-- JedisConnectionFactory --> <bean id="jedisConnectionFactory" class="org.springframework.data.redis.connection.jedis.JedisConnectionFactory"> 	<property name="hostName" value="${redis.master.ip}"/> 	<property name="port" value="${redis.master.port}"/> 	<property name="poolConfig" ref="jedisPoolConfig"/> </bean>  <bean id="redisTemplate" class="org.springframework.data.redis.core.RedisTemplate" 	  p:connectionFactory-ref="jedisConnectionFactory"> 	<property name="keySerializer"> 		<bean class="org.springframework.data.redis.serializer.JdkSerializationRedisSerializer"></bean> 	</property> 	<property name="valueSerializer"> 		<bean class="org.springframework.data.redis.serializer.JdkSerializationRedisSerializer"/> 	</property> 	<property name="hashKeySerializer"> 		<bean class="org.springframework.data.redis.serializer.JdkSerializationRedisSerializer"/> 	</property> 	<property name="hashValueSerializer"> 		<bean class="org.springframework.data.redis.serializer.JdkSerializationRedisSerializer"/> 	</property> </bean>  <!--spring cache--> <bean id="cacheManager" class="org.springframework.data.redis.cache.RedisCacheManager" 	  c:redisOperations-ref="redisTemplate"> 	<!-- 默认缓存10分钟 --> 	<property name="defaultExpiration" value="600"/> 	<property name="usePrefix" value="true"/> 	<!-- cacheName 缓存超时配置,半小时,一小时,一天 --> 	<property name="expires"> 		<map key-type="java.lang.String" value-type="java.lang.Long"> 			<entry key="halfHour" value="1800"/> 			<entry key="hour" value="3600"/> 			<entry key="oneDay" value="86400"/> 			<!-- shiro cache keys --> 			<entry key="authorizationCache" value="1800"/> 			<entry key="authenticationCache" value="1800"/> 			<entry key="activeSessionCache" value="1800"/> 		</map> 	</property> </bean> <!-- cache注解,和spring-ehcache.xml中的只能使用一个 --> <cache:annotation-driven cache-manager="cacheManager" proxy-target-class="true"/>  

项目中注解缓存只能配置一个,所以可以通过以下引入哪个配置文件来决定使用哪个缓存。

<import resource="classpath:spring/spring-ehcache.xml"/> <!-- <import resource="classpath:spring/spring-redis.xml"/>--> 

当然,可以通过其他配置搭配使用两个缓存机制。比如ecache做一级缓存,redis做二级缓存。

缓存对比.png

更加详细的使用与配置,可以参考项目中spring-shiro-training中有关spring cache的配置。

  • https://git.oschina.net/wangzhixuan/spring-shiro-training.git

写在最后

欢迎关注我的微信公众号java思维导图,下载导图源文件,以及更多java思维导图与项目资料供你学习,带你走进记忆脑图的世界。

上篇文章阅读

扫一扫关注java-mindmap公众号.jpg

本文发表于2017年08月28日 09:26
(c)注:本文转载自https://my.oschina.net/u/3080373/blog/1524728,转载目的在于传递更多信息,并不代表本网赞同其观点和对其真实性负责。如有侵权行为,请联系我们,我们会及时删除.

阅读 1731 讨论 0 喜欢 0

抢先体验

扫码体验
趣味小程序
文字表情生成器

闪念胶囊

你要过得好哇,这样我才能恨你啊,你要是过得不好,我都不知道该恨你还是拥抱你啊。

直抵黄龙府,与诸君痛饮尔。

那时陪伴我的人啊,你们如今在何方。

不出意外的话,我们再也不会见了,祝你前程似锦。

这世界真好,吃野东西也要留出这条命来看看

快捷链接
网站地图
提交友链
Copyright © 2016 - 2021 Cion.
All Rights Reserved.
京ICP备2021004668号-1