关于缓存

来源:互联网 发布:移动网络优化设置 编辑:程序博客网 时间:2024/05/24 07:42
关于缓存

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

在增删改查中,数据库查询占据了数据库操作的80%以上,而非常频繁的磁盘I/O读取操作,会导致数据库性能极度低下。而数据库的重要性就不言而喻了:
  • 数据库通常是企业应用系统最核心的部分
  • 数据库保存的数据量通常非常庞大
  • 数据库查询操作通常很频繁,有时还很复杂
在系统架构的不同层级之间,为了加快访问速度,都可以存在缓存


spring cache特性与缺憾


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




Cache注解



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


缓存策略:

  • TTL(Time To Live ) 存活期,即从缓存中创建时间点开始直到它到期的一个时间段(不管在这个时间段内有没有访问都将过期)
  • TTI(Time To Idle) 空闲期,即一个数据多久没被访问将从缓存中移除的时间

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


条件缓存


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

代码
  1. @Cacheable(value = “user”, key = “#id”, condition = “#id lt 10”)    
  2. public User conditionFindById(final Long id)  
@Cacheable(value = "user", key = "#id", condition = "#id lt 10") 
public User conditionFindById(final Long id)


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

代码
  1. @CachePut(value = “user”, key = “#id”, condition = “#result.username ne ‘zhang’”)    
  2. public User conditionSave(final User user)  
@CachePut(value = "user", key = "#id", condition = "#result.username ne 'zhang'") 
public User conditionSave(final User user)


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

代码
  1. @CachePut(value = “user”, key = “#user.id”, unless = “#result.username eq ‘zhang’”)    
  2. public User conditionSave2(final User user)  
@CachePut(value = "user", key = "#user.id", unless = "#result.username eq 'zhang'") 
public User conditionSave2(final User user)


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

代码
  1. @CacheEvict(value = “user”, key = “#user.id”, beforeInvocation = false, condition = “#result.username ne ‘zhang’”)   
  2. public User conditionDelete(final User user)  
@CacheEvict(value = "user", key = "#user.id", beforeInvocation = false, condition = "#result.username ne 'zhang'")  
public User conditionDelete(final User user)


小试牛刀,综合运用:

代码
  1. @CachePut(value = “user”, key = “#user.id”)  
  2.    public User save(User user) {  
  3.        users.add(user);  
  4.        return user;  
  5.    }  
  6.   
  7.    @CachePut(value = ”user”, key = “#user.id”)  
  8.    public User update(User user) {  
  9.        users.remove(user);  
  10.        users.add(user);  
  11.        return user;  
  12.    }  
  13.   
  14.    @CacheEvict(value = ”user”, key = “#user.id”)  
  15.    public User delete(User user) {  
  16.        users.remove(user);  
  17.        return user;  
  18.    }  
  19.   
  20.    @CacheEvict(value = ”user”, allEntries = true)  
  21.    public void deleteAll() {  
  22.        users.clear();  
  23.    }  
  24.   
  25.    @Cacheable(value = ”user”, key = “#id”)  
  26.    public User findById(final Long id) {  
  27.        System.out.println(”cache miss, invoke find by id, id:” + id);  
  28.        for (User user : users) {  
  29.            if (user.getId().equals(id)) {  
  30.                return user;  
  31.            }  
  32.        }  
  33.        return null;  
  34.    }  
 @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;}</pre>


配置ehcache与redis

spring cache集成ehcache,spring-ehcache.xml主要内容:

代码
  1. <dependency>  
  2.     <groupId>net.sf.ehcache</groupId>  
  3.     <artifactId>ehcache-core</artifactId>  
  4.     <version>${ehcache.version}</version>  
  5. </dependency>  
<dependency> 
<groupId>net.sf.ehcache</groupId>
<artifactId>ehcache-core</artifactId>
<version>${ehcache.version}</version>
</dependency>


代码
  1. <!– Spring提供的基于的Ehcache实现的缓存管理器 –>  
  2.       
  3. <!– 如果有多个ehcacheManager要在bean加上p:shared=”true” –>  
  4. <bean id=”ehcacheManager” class=“org.springframework.cache.ehcache.EhCacheManagerFactoryBean”>  
  5.      <property name=”configLocation” value=“classpath:xml/ehcache.xml”/>  
  6. </bean>  
  7.       
  8. <bean id=”cacheManager” class=“org.springframework.cache.ehcache.EhCacheCacheManager”>  
  9.      <property name=”cacheManager” ref=“ehcacheManager”/>  
  10.      <property name=”transactionAware” value=“true”/>  
  11. </bean>  
  12.       
  13. <!– cache注解,和spring-redis.xml中的只能使用一个 –>  
  14. <cache:annotation-driven cache-manager=”cacheManager” proxy-target-class=“true”/>  
<!– 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主要内容:

代码
  1. <dependency>  
  2.     <groupId>org.springframework.data</groupId>  
  3.     <artifactId>spring-data-redis</artifactId>  
  4.     <version>1.8.1.RELEASE</version>  
  5. </dependency>  
  6. <dependency>  
  7.     <groupId>org.apache.commons</groupId>  
  8.     <artifactId>commons-pool2</artifactId>  
  9.     <version>2.4.2</version>  
  10. </dependency>  
  11. <dependency>  
  12.     <groupId>redis.clients</groupId>  
  13.     <artifactId>jedis</artifactId>  
  14.     <version>2.9.0</version>  
  15. </dependency>  
<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>


代码
  1. <!– 注意需要添加Spring Data Redis等jar包 –>  
  2. <description>redis配置</description>  
  3.   
  4. <bean id=”jedisPoolConfig” class=“redis.clients.jedis.JedisPoolConfig”>  
  5.     <property name=”maxIdle” value={redis.pool.maxIdle}"</span><span>/&gt;&nbsp;&nbsp;</span></span></li><li><span>&nbsp;&nbsp;&nbsp;&nbsp;&lt;property&nbsp;name=<span class="string">"maxTotal"</span><span>&nbsp;value=</span><span class="string">"{redis.pool.maxActive}”/>  
  6.     <property name=”maxWaitMillis” value={redis.pool.maxWait}"</span><span>/&gt;&nbsp;&nbsp;</span></span></li><li><span>&nbsp;&nbsp;&nbsp;&nbsp;&lt;property&nbsp;name=<span class="string">"testOnBorrow"</span><span>&nbsp;value=</span><span class="string">"{redis.pool.testOnBorrow}”/>  
  7.     <property name=”testOnReturn” value={redis.pool.testOnReturn}"</span><span>/&gt;&nbsp;&nbsp;</span></span></li><li><span>&lt;/bean&gt;&nbsp;&nbsp;</span></li><li><span>&nbsp;&nbsp;</span></li><li><span>&lt;!--&nbsp;JedisConnectionFactory&nbsp;--&gt;&nbsp;&nbsp;</span></li><li><span>&lt;bean&nbsp;id=<span class="string">"jedisConnectionFactory"</span><span>&nbsp;class=</span><span class="string">"org.springframework.data.redis.connection.jedis.JedisConnectionFactory"</span><span>&gt;&nbsp;&nbsp;</span></span></li><li><span>&nbsp;&nbsp;&nbsp;&nbsp;&lt;property&nbsp;name=<span class="string">"hostName"</span><span>&nbsp;value=</span><span class="string">"{redis.master.ip}”/>  
  8.     <property name=”port” value=“${redis.master.port}”/>  
  9.     <property name=”poolConfig” ref=“jedisPoolConfig”/>  
  10. </bean>  
  11.   
  12. <bean id=”redisTemplate” class=“org.springframework.data.redis.core.RedisTemplate”  
  13.       p:connectionFactory-ref=”jedisConnectionFactory”>  
  14.     <property name=”keySerializer”>  
  15.         <bean class=”org.springframework.data.redis.serializer.JdkSerializationRedisSerializer”></bean>  
  16.     </property>  
  17.     <property name=”valueSerializer”>  
  18.         <bean class=”org.springframework.data.redis.serializer.JdkSerializationRedisSerializer”/>  
  19.     </property>  
  20.     <property name=”hashKeySerializer”>  
  21.         <bean class=”org.springframework.data.redis.serializer.JdkSerializationRedisSerializer”/>  
  22.     </property>  
  23.     <property name=”hashValueSerializer”>  
  24.         <bean class=”org.springframework.data.redis.serializer.JdkSerializationRedisSerializer”/>  
  25.     </property>  
  26. </bean>  
  27.   
  28. <!–spring cache–>  
  29. <bean id=”cacheManager” class=“org.springframework.data.redis.cache.RedisCacheManager”  
  30.       c:redisOperations-ref=”redisTemplate”>  
  31.     <!– 默认缓存10分钟 –>  
  32.     <property name=”defaultExpiration” value=“600”/>  
  33.     <property name=”usePrefix” value=“true”/>  
  34.     <!– cacheName 缓存超时配置,半小时,一小时,一天 –>  
  35.     <property name=”expires”>  
  36.         <map key-type=”java.lang.String” value-type=“java.lang.Long”>  
  37.             <entry key=”halfHour” value=“1800”/>  
  38.             <entry key=”hour” value=“3600”/>  
  39.             <entry key=”oneDay” value=“86400”/>  
  40.             <!– shiro cache keys –>  
  41.             <entry key=”authorizationCache” value=“1800”/>  
  42.             <entry key=”authenticationCache” value=“1800”/>  
  43.             <entry key=”activeSessionCache” value=“1800”/>  
  44.         </map>  
  45.     </property>  
  46. </bean>  
  47. <!– cache注解,和spring-ehcache.xml中的只能使用一个 –>  
  48. <cache:annotation-driven cache-manager=”cacheManager” proxy-target-class=“true”/>  
<!– 注意需要添加Spring Data Redis等jar包 –> 
<description>redis配置</description>

<bean id=”jedisPoolConfig” class=”redis.clients.jedis.JedisPoolConfig”>
<property name=”maxIdle” value=”redis.pool.maxIdle/><propertyname=maxTotalvalue={redis.pool.maxActive}”/>
<property name=”maxWaitMillis” value=”redis.pool.maxWait/><propertyname=testOnBorrowvalue={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/><propertyname=portvalue={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”/>

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

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



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

原创粉丝点击
热门问题 老师的惩罚 人脸识别 我在镇武司摸鱼那些年 重生之率土为王 我在大康的咸鱼生活 盘龙之生命进化 天生仙种 凡人之先天五行 春回大明朝 姑娘不必设防,我是瞎子 换手机号了淘宝账号怎么办 qq登录id密码忘记怎么办 iphone商店密码忘记了怎么办 淘宝账号被限制登入怎么办 手机换号码了qq登不上怎么办 换手机了qq登不上怎么办 微信帐号和密码错误怎么办 高考生忘记登录密码怎么办 高考生登录密码丢了怎么办 高考志愿登录密码忘了怎么办 电视声音和画面不同步怎么办 苹果5s不能开机怎么办 红米手机老是闪退怎么办 苹果7plus打字卡怎么办 手机总是出现无响应怎么办 手机淘宝怎么打不开了怎么办 淘宝买东西卖家不同意退货怎么办 苹果自带浏览器不能上网怎么办 淘宝账号买不了东西怎么办 支付宝被限制登录怎么办 微信登录不上 钱怎么办 淘宝账号买家权限被限制怎么办 淘宝中店新品打不开怎么办 旺旺号被限制有退款怎么办 登陆微信收不到验证码怎么办 淘宝店注册成功后怎么办 充电宝掉进水里怎么办 空光盘读不出来怎么办 苹果8plus丢了怎么办 苹果8plus掉了怎么办 淘宝账户被限制使用怎么办 飞利浦电脑显示器黑屏怎么办打开 微信忘记密码手机号停用怎么办 淘宝账号登录密码忘记了怎么办 淘宝支付密码输错了怎么办 淘宝支付密码忘记了怎么办 淘宝货品上架后显示过期怎么办 被淘宝客监控了怎么办 助学贷款支付宝账号忘记怎么办 离婚支付宝的钱怎么办 扫码加载不出来怎么办