Redis集成Spring筆記

1. 依賴包安裝

<dependency>
    <groupId>org.springframework.data</groupId>
    <artifactId>spring-data-redis</artifactId>
    <version>1.7.5.RELEASE</version>
</dependency>
<dependency>
    <groupId>redis.clientsgroupId>
    <artifactId>jedis</artifactId>
    <version>2.9.0</version>
</dependency>

2. Spring 項目集成進緩存支持
要啟用緩存支持,我們需要創(chuàng)建一個新的 CacheManager bean伤靠。CacheManager 接口有很多實現(xiàn),本文演示的是和 Redis 的集成,自然就是用 RedisCacheManager 了播聪。Redis 不是應用的共享內存椒振,它只是一個內存服務器昭伸,就像 MySql 似的,我們需要將應用連接到它并使用某種“語言”進行交互澎迎,因此我們還需要一個連接工廠以及一個 Spring 和 Redis 對話要用的 RedisTemplate庐杨,這些都是 Redis 緩存所必需的配置,把它們都放在自定義的 CachingConfigurerSupport 中:

package com.defonds.bdp.cache.redis;

import org.springframework.cache.CacheManager;
import org.springframework.cache.annotation.CachingConfigurerSupport;
import org.springframework.cache.annotation.EnableCaching;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.data.redis.cache.RedisCacheManager;
import org.springframework.data.redis.connection.RedisConnectionFactory;
import org.springframework.data.redis.connection.jedis.JedisConnectionFactory;
import org.springframework.data.redis.core.RedisTemplate;

@Configuration
@EnableCaching
public class RedisCacheConfig extends CachingConfigurerSupport {

    @Bean
    public JedisConnectionFactory redisConnectionFactory() {
        JedisConnectionFactory redisConnectionFactory = new JedisConnectionFactory();

        // Defaults
        redisConnectionFactory.setHostName("192.168.1.166");
        redisConnectionFactory.setPort(6379);
        return redisConnectionFactory;
    }

    @Bean
    public RedisTemplate<String, String> redisTemplate(RedisConnectionFactory cf) {
        RedisTemplate<String, String> redisTemplate = new RedisTemplate<String, String>();
        redisTemplate.setConnectionFactory(cf);
        return redisTemplate;
    }

    @Bean
    public CacheManager cacheManager(RedisTemplate redisTemplate) {
        RedisCacheManager cacheManager = new RedisCacheManager(redisTemplate);

        // Number of seconds before expiration. Defaults to unlimited (0)
        cacheManager.setDefaultExpiration(3000); // Sets the default expire time (in seconds)
        return cacheManager;
    }
    
}

當然也別忘了把這些 bean 注入 Spring夹供,不然配置無效灵份。在 applicationContext.xml 中加入以下:

<context:component-scan base-package="com.defonds.bdp.cache.redis" />  

3. 緩存某些方法的執(zhí)行結果
設置好緩存配置之后我們就可以使用 @Cacheable 注解來緩存方法執(zhí)行的結果了,比如根據(jù)省份名檢索城市的 provinceCities 方法和根據(jù) city_code 檢索城市的 searchCity 方法:

    // R
    @Cacheable("provinceCities")
    public List<City> provinceCities(String province) {
        logger.debug("province=" + province);
        return this.cityMapper.provinceCities(province);
    }
    
    // R
    @Cacheable("searchCity")
    public City searchCity(String city_code){
        logger.debug("city_code=" + city_code);
        return this.cityMapper.searchCity(city_code);   
    }

4. 緩存數(shù)據(jù)一致性保證
CRUD (Create 創(chuàng)建哮洽,Retrieve 讀取填渠,Update 更新,Delete 刪除) 操作中袁铐,除了 R 具備冪等性揭蜒,其他三個發(fā)生的時候都可能會造成緩存結果和數(shù)據(jù)庫不一致。為了保證緩存數(shù)據(jù)的一致性剔桨,在進行 CUD 操作的時候我們需要對可能影響到的緩存進行更新或者清除屉更。

 // C
 @CacheEvict(value = { "provinceCities"}, allEntries = true)
 public void insertCity(String city_code, String city_jb, 
   String province_code, String city_name,
   String city, String province) {
  City cityBean = new City();
  cityBean.setCityCode(city_code);
  cityBean.setCityJb(city_jb);
  cityBean.setProvinceCode(province_code);
  cityBean.setCityName(city_name);
  cityBean.setCity(city);
  cityBean.setProvince(province);
  this.cityMapper.insertCity(cityBean);
 }

 // U
 @CacheEvict(value = { "provinceCities", "searchCity" }, allEntries = true)
 public int renameCity(String city_code, String city_name) {
  City city = new City();
  city.setCityCode(city_code);
  city.setCityName(city_name);
  this.cityMapper.renameCity(city);
  return 1;
 }
 
 // D
 @CacheEvict(value = { "provinceCities", "searchCity" }, allEntries = true)
 public int deleteCity(String city_code) {
  this.cityMapper.deleteCity(city_code);
  return 1;
 }

業(yè)務考慮,本示例用的都是 @CacheEvict 清除緩存洒缀。如果你的 CUD 能夠返回 City 實例瑰谜,也可以使用 @CachePut 更新緩存策略欺冀。筆者推薦能用 @CachePut 的地方就不要用 @CacheEvict,因為后者將所有相關方法的緩存都清理掉萨脑,比如上面三個方法中的任意一個被調用了的話隐轩,provinceCities 方法的所有緩存將被清除。

5. 自定義緩存數(shù)據(jù) key 生成策略

對于使用 @Cacheable 注解的方法渤早,每個緩存的 key 生成策略默認使用的是參數(shù)名+參數(shù)值职车,比如以下方法:

@Cacheable("users")
public User findByUsername(String username)

這個方法的緩存將保存于 key 為 users~keys 的緩存下,對于 username 取值為 "趙德芳" 的緩存鹊杖,key 為 "username-趙德芳"悴灵。一般情況下沒啥問題,二般情況如方法 key 取值相等然后參數(shù)名也一樣的時候就出問題了骂蓖,如:

@Cacheable("users")
public Integer getLoginCountByUsername(String username)

這個方法的緩存也將保存于 key 為 users~keys 的緩存下积瞒。對于 username 取值為 "趙德芳" 的緩存,key 也為 "username-趙德芳"登下,將另外一個方法的緩存覆蓋掉茫孔。
解決辦法是使用自定義緩存策略,對于同一業(yè)務(同一業(yè)務邏輯處理的方法被芳,哪怕是集群/分布式系統(tǒng))缰贝,生成的 key 始終一致,對于不同業(yè)務則不一致:

 @Bean
 public KeyGenerator customKeyGenerator() {
  return new KeyGenerator() {
   @Override
   public Object generate(Object o, Method method, Object... objects) {
    StringBuilder sb = new StringBuilder();
    sb.append(o.getClass().getName());
    sb.append(method.getName());
    for (Object obj : objects) {
     sb.append(obj.toString());
    }
    return sb.toString();
   }
  };
 }

于是上述兩個方法筐钟,對于 username 取值為 "趙德芳" 的緩存揩瞪,雖然都還是存放在 key 為 users~keys 的緩存下,但由于 key 分別為 "類名-findByUsername-username-趙德芳" 和 "類名-getLoginCountByUsername-username-趙德芳"篓冲,所以也不會有問題。
這對于集群系統(tǒng)宠哄、分布式系統(tǒng)之間共享緩存很重要壹将,真正實現(xiàn)了分布式緩存。
筆者建議:緩存方法的 @Cacheable 最好使用方法名毛嫉,避免不同的方法的 @Cacheable 值一致诽俯,然后再配以以上緩存策略。

6. 緩存的驗證

7. 注意事項

  • 要緩存的 Java 對象必須實現(xiàn) Serializable 接口
  • 緩存的生命周期我們可以配置承粤,然后托管 Spring CacheManager暴区,不要試圖通過 redis-cli 命令行去管理緩存。
  • CacheManager 必須設置緩存過期時間辛臊,否則緩存對象將永不過期仙粱,這樣做的原因如上,避免一些野數(shù)據(jù)“永久保存”彻舰。此外伐割,設置緩存過期時間也有助于資源利用最大化候味,因為緩存里保留的永遠是熱點數(shù)據(jù)。
  • 緩存適用于讀多寫少的場合隔心,查詢時緩存命中率很低白群、寫操作很頻繁等場景不適宜用緩存。
最后編輯于
?著作權歸作者所有,轉載或內容合作請聯(lián)系作者
  • 序言:七十年代末硬霍,一起剝皮案震驚了整個濱河市帜慢,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌唯卖,老刑警劉巖崖堤,帶你破解...
    沈念sama閱讀 218,546評論 6 507
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異耐床,居然都是意外死亡密幔,警方通過查閱死者的電腦和手機,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,224評論 3 395
  • 文/潘曉璐 我一進店門撩轰,熙熙樓的掌柜王于貴愁眉苦臉地迎上來胯甩,“玉大人,你說我怎么就攤上這事堪嫂≠梭铮” “怎么了?”我有些...
    開封第一講書人閱讀 164,911評論 0 354
  • 文/不壞的土叔 我叫張陵皆串,是天一觀的道長淹办。 經常有香客問我,道長恶复,這世上最難降的妖魔是什么怜森? 我笑而不...
    開封第一講書人閱讀 58,737評論 1 294
  • 正文 為了忘掉前任,我火速辦了婚禮谤牡,結果婚禮上副硅,老公的妹妹穿的比我還像新娘。我一直安慰自己翅萤,他們只是感情好恐疲,可當我...
    茶點故事閱讀 67,753評論 6 392
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著套么,像睡著了一般培己。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上胚泌,一...
    開封第一講書人閱讀 51,598評論 1 305
  • 那天省咨,我揣著相機與錄音,去河邊找鬼诸迟。 笑死茸炒,一個胖子當著我的面吹牛愕乎,可吹牛的內容都是我干的。 我是一名探鬼主播壁公,決...
    沈念sama閱讀 40,338評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼感论,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了紊册?” 一聲冷哼從身側響起比肄,我...
    開封第一講書人閱讀 39,249評論 0 276
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎囊陡,沒想到半個月后芳绩,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經...
    沈念sama閱讀 45,696評論 1 314
  • 正文 獨居荒郊野嶺守林人離奇死亡撞反,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內容為張勛視角 年9月15日...
    茶點故事閱讀 37,888評論 3 336
  • 正文 我和宋清朗相戀三年妥色,在試婚紗的時候發(fā)現(xiàn)自己被綠了。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片遏片。...
    茶點故事閱讀 40,013評論 1 348
  • 序言:一個原本活蹦亂跳的男人離奇死亡嘹害,死狀恐怖,靈堂內的尸體忽然破棺而出吮便,到底是詐尸還是另有隱情笔呀,我是刑警寧澤,帶...
    沈念sama閱讀 35,731評論 5 346
  • 正文 年R本政府宣布髓需,位于F島的核電站许师,受9級特大地震影響,放射性物質發(fā)生泄漏僚匆。R本人自食惡果不足惜微渠,卻給世界環(huán)境...
    茶點故事閱讀 41,348評論 3 330
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望白热。 院中可真熱鬧敛助,春花似錦、人聲如沸屋确。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,929評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽攻臀。三九已至,卻和暖如春纱昧,著一層夾襖步出監(jiān)牢的瞬間刨啸,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 33,048評論 1 270
  • 我被黑心中介騙來泰國打工识脆, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留设联,地道東北人善已。 一個月前我還...
    沈念sama閱讀 48,203評論 3 370
  • 正文 我出身青樓,卻偏偏與公主長得像离例,于是被迫代替她去往敵國和親换团。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當晚...
    茶點故事閱讀 44,960評論 2 355

推薦閱讀更多精彩內容

  • Spring Cloud為開發(fā)人員提供了快速構建分布式系統(tǒng)中一些常見模式的工具(例如配置管理宫蛆,服務發(fā)現(xiàn)艘包,斷路器,智...
    卡卡羅2017閱讀 134,657評論 18 139
  • Spring Boot 參考指南 介紹 轉載自:https://www.gitbook.com/book/qbgb...
    毛宇鵬閱讀 46,822評論 6 342
  • 之前用SpringBoot+MyBatisPlus+SpringMVC整合搭建了一個基礎web開發(fā)框架耀盗,使用這三個...
    z77z閱讀 4,461評論 2 25
  • 翻看手機相冊叛拷,不知不覺自己又給小陽臺的簕杜鵑拍了好多照片呢舌厨。 每次在陽臺放松看到它,都會忍不住拍下幾張忿薇。陰天裙椭,雨天...
    吾塔塔閱讀 245評論 0 2
  • 在護理精細化管理下,我們科室進行了整頓煌恢、清掃骇陈,優(yōu)化科室環(huán)境,創(chuàng)造了一個舒適整潔的工作場所瑰抵。 在督導訓練師指導下你雌,...
    林麗麗閱讀 725評論 0 0