Spring Cache 思維導(dǎo)圖

轉(zhuǎn)載https://my.oschina.net/u/3080373/blog/1524728

關(guān)于緩存

緩存是實(shí)際工作中非常常用的一種提高性能的方法于微。而在java中丐怯,所謂緩存耍攘,就是將程序或系統(tǒng)經(jīng)常要調(diào)用的對(duì)象存在內(nèi)存中低飒,再次調(diào)用時(shí)可以快速?gòu)膬?nèi)存中獲取對(duì)象渴频,不必再去創(chuàng)建新的重復(fù)的實(shí)例。這樣做可以減少系統(tǒng)開銷将塑,提高系統(tǒng)效率脉顿。

在增刪改查中,數(shù)據(jù)庫(kù)查詢占據(jù)了數(shù)據(jù)庫(kù)操作的80%以上抬旺,而非常頻繁的磁盤I/O讀取操作弊予,會(huì)導(dǎo)致數(shù)據(jù)庫(kù)性能極度低下。而數(shù)據(jù)庫(kù)的重要性就不言而喻了:

  • 數(shù)據(jù)庫(kù)通常是企業(yè)應(yīng)用系統(tǒng)最核心的部分
  • 數(shù)據(jù)庫(kù)保存的數(shù)據(jù)量通常非常龐大
  • 數(shù)據(jù)庫(kù)查詢操作通常很頻繁开财,有時(shí)還很復(fù)雜

在系統(tǒng)架構(gòu)的不同層級(jí)之間汉柒,為了加快訪問(wèn)速度,都可以存在緩存

image

spring cache 特性與缺憾

現(xiàn)在市場(chǎng)上主流的緩存框架有ehcache责鳍、redis碾褂、memcached。spring cache可以通過(guò)簡(jiǎn)單的配置就可以搭配使用起來(lái)历葛。其中使用注解方式是最簡(jiǎn)單的正塌。

image

Cache注解

image

從以上的注解中可以看出,雖然使用注解的確方便恤溶,但是缺少靈活的緩存策略乓诽,

緩存策略:

  • TTL(Time To Live ) 存活期,即從緩存中創(chuàng)建時(shí)間點(diǎn)開始直到它到期的一個(gè)時(shí)間段(不管在這個(gè)時(shí)間段內(nèi)有沒(méi)有訪問(wèn)都將過(guò)期)
  • TTI(Time To Idle) 空閑期咒程,即一個(gè)數(shù)據(jù)多久沒(méi)被訪問(wèn)將從緩存中移除的時(shí)間

項(xiàng)目中可能有很多緩存的TTL不相同鸠天,這時(shí)候就需要編碼式使用編寫緩存。

條件緩存

根據(jù)運(yùn)行流程帐姻,如下@Cacheable將在執(zhí)行方法之前( #result還拿不到返回值)判斷condition稠集,如果返回true,則查緩存饥瓷;

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

如下@CachePut將在執(zhí)行完方法后(#result就能拿到返回值了)判斷condition剥纷,如果返回true,則放入緩存

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

如下@CachePut將在執(zhí)行完方法后(#result就能拿到返回值了)判斷unless呢铆,如果返回false晦鞋,則放入緩存;(即跟condition相反)

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

如下@CacheEvict棺克, beforeInvocation=false表示在方法執(zhí)行之后調(diào)用(#result能拿到返回值了)鳖宾;且判斷condition,如果返回true逆航,則移除緩存;

@CacheEvict(value = "user", key = "#user.id", beforeInvocation = false, condition = "#result.username ne 'zhang'") 
public User conditionDelete(final User user)   
  • 小試牛刀渔肩,綜合運(yùn)用:
    @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主要內(nèi)容:
<dependency>
    <groupId>net.sf.ehcache</groupId>
    <artifactId>ehcache-core</artifactId>
    <version>${ehcache.version}</version>
</dependency>
<!-- Spring提供的基于的Ehcache實(shí)現(xiàn)的緩存管理器 -->
    
<!-- 如果有多個(gè)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中的只能使用一個(gè) -->
<cache:annotation-driven cache-manager="cacheManager" proxy-target-class="true"/>
  • spring cache集成redis,spring-redis.xml主要內(nèi)容:
<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">
    <!-- 默認(rèn)緩存10分鐘 -->
    <property name="defaultExpiration" value="600"/>
    <property name="usePrefix" value="true"/>
    <!-- cacheName 緩存超時(shí)配置抹剩,半小時(shí)撑帖,一小時(shí),一天 -->
    <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中的只能使用一個(gè) -->
<cache:annotation-driven cache-manager="cacheManager" proxy-target-class="true"/>

項(xiàng)目中注解緩存只能配置一個(gè)胡嘿,所以可以通過(guò)以下引入哪個(gè)配置文件來(lái)決定使用哪個(gè)緩存。

<import resource="classpath:spring/spring-ehcache.xml"/>
![image](http://upload-images.jianshu.io/upload_images/10406068-8fbb94211c475235?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240)
 <!-- <import resource="classpath:spring/spring-redis.xml"/>-->

當(dāng)然钳踊,可以通過(guò)其他配置搭配使用兩個(gè)緩存機(jī)制衷敌。比如ecache做一級(jí)緩存,redis做二級(jí)緩存拓瞪。

image
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末缴罗,一起剝皮案震驚了整個(gè)濱河市,隨后出現(xiàn)的幾起案子祭埂,更是在濱河造成了極大的恐慌面氓,老刑警劉巖,帶你破解...
    沈念sama閱讀 218,204評(píng)論 6 506
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件蛆橡,死亡現(xiàn)場(chǎng)離奇詭異舌界,居然都是意外死亡,警方通過(guò)查閱死者的電腦和手機(jī)泰演,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,091評(píng)論 3 395
  • 文/潘曉璐 我一進(jìn)店門呻拌,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái),“玉大人粥血,你說(shuō)我怎么就攤上這事柏锄。” “怎么了复亏?”我有些...
    開封第一講書人閱讀 164,548評(píng)論 0 354
  • 文/不壞的土叔 我叫張陵趾娃,是天一觀的道長(zhǎng)。 經(jīng)常有香客問(wèn)我缔御,道長(zhǎng)抬闷,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 58,657評(píng)論 1 293
  • 正文 為了忘掉前任耕突,我火速辦了婚禮笤成,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘眷茁。我一直安慰自己炕泳,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,689評(píng)論 6 392
  • 文/花漫 我一把揭開白布上祈。 她就那樣靜靜地躺著培遵,像睡著了一般浙芙。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上籽腕,一...
    開封第一講書人閱讀 51,554評(píng)論 1 305
  • 那天嗡呼,我揣著相機(jī)與錄音,去河邊找鬼皇耗。 笑死南窗,一個(gè)胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的郎楼。 我是一名探鬼主播万伤,決...
    沈念sama閱讀 40,302評(píng)論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼箭启!你這毒婦竟也來(lái)了壕翩?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 39,216評(píng)論 0 276
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤傅寡,失蹤者是張志新(化名)和其女友劉穎放妈,沒(méi)想到半個(gè)月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體荐操,經(jīng)...
    沈念sama閱讀 45,661評(píng)論 1 314
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡芜抒,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,851評(píng)論 3 336
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了托启。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片宅倒。...
    茶點(diǎn)故事閱讀 39,977評(píng)論 1 348
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖屯耸,靈堂內(nèi)的尸體忽然破棺而出拐迁,到底是詐尸還是另有隱情,我是刑警寧澤疗绣,帶...
    沈念sama閱讀 35,697評(píng)論 5 347
  • 正文 年R本政府宣布缓淹,位于F島的核電站,受9級(jí)特大地震影響塔逃,放射性物質(zhì)發(fā)生泄漏湾盗。R本人自食惡果不足惜丙挽,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,306評(píng)論 3 330
  • 文/蒙蒙 一凳怨、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧李剖,春花似錦、人聲如沸德玫。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,898評(píng)論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)。三九已至,卻和暖如春坐桩,著一層夾襖步出監(jiān)牢的瞬間膘螟,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 33,019評(píng)論 1 270
  • 我被黑心中介騙來(lái)泰國(guó)打工俘闯, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人遮婶。 一個(gè)月前我還...
    沈念sama閱讀 48,138評(píng)論 3 370
  • 正文 我出身青樓,卻偏偏與公主長(zhǎng)得像清钥,于是被迫代替她去往敵國(guó)和親怖侦。 傳聞我的和親對(duì)象是個(gè)殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,927評(píng)論 2 355

推薦閱讀更多精彩內(nèi)容

  • Spring Cloud為開發(fā)人員提供了快速構(gòu)建分布式系統(tǒng)中一些常見模式的工具(例如配置管理急凰,服務(wù)發(fā)現(xiàn),斷路器猜年,智...
    卡卡羅2017閱讀 134,657評(píng)論 18 139
  • Spring Boot 參考指南 介紹 轉(zhuǎn)載自:https://www.gitbook.com/book/qbgb...
    毛宇鵬閱讀 46,811評(píng)論 6 342
  • 親愛的lucky, 今天是你在媽媽肚子里的37W+1D一罩,期待你的到來(lái)。在漫漫人生長(zhǎng)河中暖夭,你的成長(zhǎng)是不可逆的裕菠,為了留...
    拉克豬豬說(shuō)閱讀 566評(píng)論 0 3
  • 論說(shuō)天寒你應(yīng)歸咬清,挑燈笑把火爐圍。 風(fēng)來(lái)不忍窗簾閉奴潘,盼落星光盼日暉掘剪。 ————丁酉年癸丑...
    樂(lè)阿蘭那行者閱讀 519評(píng)論 4 7
  • 記得辯論隊(duì)招新的時(shí)候,面對(duì)滿屋子的大一小鮮肉奈虾,隊(duì)長(zhǎng)一臉嚴(yán)肅的從口中吐出這樣一句話:“進(jìn)了辯論隊(duì)夺谁,就要做好逃課的準(zhǔn)備...
    江南才客閱讀 403評(píng)論 0 1