Redis統合Springノート

6567 ワード

1.依存パッケージのインストール

    org.springframework.data
    spring-data-redis
    1.7.5.RELEASE


    redis.clientsgroupId>
    jedis
    2.9.0


2.Springプロジェクト統合キャッシュサポートキャッシュサポートを有効にするには、新しいCacheManager beanを作成する必要があります.CacheManagerインタフェースには多くの実装があり、ここでは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 redisTemplate(RedisConnectionFactory cf) {
        RedisTemplate redisTemplate = new RedisTemplate();
        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に注入することも忘れないでください.そうしないと、構成が無効になります.アプリケーションContext.xmlには次のものが含まれます.
  

3.いくつかのメソッドの実行結果をキャッシュ構成を設定すると、@Cacheable注記を使用してメソッドの実行結果をキャッシュできます.たとえば、省名に基づいて都市を取得するprovinceCitiesメソッドやcity_に基づいてcode検索都市のsearchCityメソッド:
    // R
    @Cacheable("provinceCities")
    public List 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.キャッシュデータ整合性保証CRUD(Create作成、Retrieve読み出し、Update更新、Delete削除)操作では、Rがべき乗等性を備えているほか、3つの発生時にキャッシュ結果とデータベースが一致しない可能性があります.キャッシュデータの一貫性を確保するために、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;
 }

ビジネス上、この例では@CacheEveictキャッシュのクリアを使用します.CUDがCityインスタンスを返すことができる場合は、@CachePutを使用してキャッシュポリシーを更新することもできます.筆者は@CachePutが使えるところは@CacheEveictを使わないことをお勧めします.後者はすべての関連メソッドのキャッシュをクリーンアップします.例えば、上記の3つのメソッドのいずれかが呼び出されると、provinceCitiesメソッドのすべてのキャッシュがクリアされます.
5.カスタムキャッシュデータkey生成ポリシー
@Cacheable注記を使用する方法では、各キャッシュのkey生成ポリシーのデフォルトでは、次のようなパラメータ名+パラメータ値が使用されます.
@Cacheable("users")
public User findByUsername(String username)

この方法のキャッシュはkeyがusers~keysのキャッシュに保存され、usernameに対して「趙徳芳」のキャッシュを取り、keyは「username-趙徳芳」である.一般的には問題ありませんが、方法keyの値が等しい場合、パラメータ名も同じ場合に問題が発生します.
@Cacheable("users")
public Integer getLoginCountByUsername(String username)

このメソッドのキャッシュもkeyがusers~keysのキャッシュに保存される.usernameが「趙徳芳」のキャッシュをとる場合、keyも「username-趙徳芳」となり、別のメソッドのキャッシュを上書きします.解決策は、カスタムキャッシュポリシーを使用して、クラスタ/分散システムであっても、同じビジネス(クラスタ/分散システム)に対して生成されたkeyは常に一致し、異なるビジネスに対しては一致しません.
 @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();
   }
  };
 }

そこで、上記の2つの方法は、usernameの値が「趙徳芳」のキャッシュについても、keyがusers~keysのキャッシュに格納されているが、keyはそれぞれ「クラス名-findByUsername-username-趙徳芳」と「クラス名-getLoginCountByUsername-username-趙徳芳」であるため、問題はない.これはクラスタシステム、分散システム間の共有キャッシュにとって重要であり、本当に分散キャッシュを実現している.筆者は、キャッシュメソッドの@Cacheableは、メソッド名を使用して、異なるメソッドの@Cacheable値が一致しないようにしてから、上記のキャッシュポリシーを割り当てることをお勧めします.
6.キャッシュの検証
7.注意事項
  • キャッシュするJavaオブジェクトは、Serializableインタフェース
  • を実装する必要があります.
  • キャッシュのライフサイクルを構成し、redis-cliコマンドラインでキャッシュを管理しようとしないでSpring CacheManagerを管理できます.
  • CacheManagerでは、キャッシュの有効期限を設定する必要があります.そうしないと、キャッシュ・オブジェクトは有効期限が切れません.このような理由で、野生のデータの「永続保存」を避けることができます.また、キャッシュの有効期限を設定することは、キャッシュに保持されているホットスポットデータが常に存在するため、リソースの利用を最大化するのに役立ちます.
  • キャッシュは読み書きが少ない場合に適しており、クエリー時のキャッシュヒット率が低く、書き込み操作が頻繁であるなどのシーンではキャッシュに適していない.