Spring思惟導圖,讓Spring再也不難懂(cache篇)

關於緩存java

緩存是實際工做中很是經常使用的一種提升性能的方法。而在java中,所謂緩存,就是將程序或系統常常要調用的對象存在內存中,再次調用時能夠快速從內存中獲取對象,沒必要再去建立新的重複的實例。這樣作能夠減小系統開銷,提升系統效率。git

在增刪改查中,數據庫查詢佔據了數據庫操做的80%以上,而很是頻繁的磁盤I/O讀取操做,會致使數據庫性能極度低下。而數據庫的重要性就不言而喻了:redis

  • 數據庫一般是企業應用系統最核心的部分
  • 數據庫保存的數據量一般很是龐大
  • 數據庫查詢操做一般很頻繁,有時還很複雜

在系統架構的不一樣層級之間,爲了加快訪問速度,均可以存在緩存spring

緩存不一樣層級的做用.png

spring cache特性與缺憾數據庫

如今市場上主流的緩存框架有ehcache、redis、memcached。spring cache能夠經過簡單的配置就能夠搭配使用起來。其中使用註解方式是最簡單的。apache

特性與缺憾.png

Cache註解緩存

緩存註解.png

從以上的註解中能夠看出,雖然使用註解的確方便,可是缺乏靈活的緩存策略,微信

緩存策略:架構

  • TTL(Time To Live ) 存活期,即從緩存中建立時間點開始直到它到期的一個時間段(無論在這個時間段內有沒有訪問都將過時)mvc

  • 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的配置。

寫在最後

歡迎關注個人微信公衆號java思惟導圖,下載導圖源文件,以及更多java思惟導圖與項目資料供你學習,帶你走進記憶腦圖的世界。

關注公衆號並回復「思惟導圖」即刻下載源xmind導圖。

上篇文章閱讀

掃一掃關注java-mindmap公衆號.jpg

相關文章
相關標籤/搜索