Redis 통합 Spring 결합 캐 시 인 스 턴 스 사용

17710 단어 RedisSpring캐 시
1.Redis 소개
레 디 스 가 뭐야?
      redis 는 key-value 저장 시스템 입 니 다.Memcached 와 유사 합 니 다.저 장 된 value 형식 이 상대 적 으로 많 습 니 다.string(문자열),list(링크),set(집합),zset(sorted set-질서 있 는 집합)과 hash(해시 형식)를 포함 합 니 다.이러한 데이터 형식 은 push/pop,add/remove 및 교차 집합 과 차 집합 및 더욱 풍부 한 조작 을 지원 하 며,이러한 조작 은 모두 원자 적 이다.이 를 바탕 으로 redis 는 다양한 방식 의 정렬 을 지원 합 니 다.memcached 와 마찬가지 로 효율 을 확보 하기 위해 데 이 터 는 모두 메모리 에 캐 시 되 어 있 습 니 다.다른 것 은 redis 가 주기 적 으로 업 데 이 트 된 데 이 터 를 디스크 에 기록 하거나 수정 작업 을 추가 기록 파일 에 기록 하 며 이 를 바탕 으로 master-slave(주종)동기 화 를 실현 하 는 것 이다.
그것 은 어떤 특징 이 있 습 니까?
(1)Redis 데이터 베 이 스 는 완전히 메모리 에 있 습 니 다.디스크 를 사용 하면 지속 성에 만 사 용 됩 니 다.
(2)많은 키 데이터 에 비해 Redis 는 비교적 풍부 한 데이터 형식 을 가지 고 있다.
(3)Redis 는 서버 에서 임의의 수량 으로 데 이 터 를 복사 할 수 있다.
레 디 스 우세?
 (1)매우 빠 름:Redis 의 속도 가 매우 빠 르 고 1 초 에 약 11 만 집합 을 실행 할 수 있 으 며 1 초 에 약 81000+개의 기록 을 실행 할 수 있 습 니 다.
 (2)풍부 한 데이터 형식 을 지원 합 니 다.Redis 는 최대 다수의 개발 자 들 이 목록,집합,질서 있 는 집합,해시 데이터 형식 을 알 고 있 습 니 다.이것 은 그것 으로 하여 금 여러 가지 문 제 를 쉽게 해결 하 게 한다.왜냐하면 우 리 는 어떤 문제 가 그것 을 통 해 데이터 형식 을 처리 하 는 것 이 더 좋 은 지 알 고 있 기 때문이다.
(3)작업 은 모두 원자 성 입 니 다.모든 Redis 작업 은 원자 입 니 다.이 는 두 클 라 이언 트 가 동시에 방문 하 는 Redis 서버 가 업 데 이 트 된 값 을 얻 을 수 있 도록 보장 합 니 다.
(4)다기 능 유 틸 리 티:Redis 는 여러 가지 유 틸 리 티 도구 입 니 다.예 를 들 어 캐 시,메시지,대기 열 에서 사용 할 수 있 습 니 다(Redis 원생 지원 게시/구독).짧 은 데이터,응용 프로그램,예 를 들 어 웹 응용 프로그램 세 션,웹 명중 계수 등 입 니 다.
Redis 단점?
(1)단일 스 레 드
(2)메모리 소모
2.인 스 턴 스 사용
본문 은 maven+eclipse+sping 을 사용 합 니 다.
1,jar 가방 도입

  <!--Redis start --> 
<dependency> 
  <groupId>org.springframework.data</groupId> 
  <artifactId>spring-data-redis</artifactId> 
  <version>1.6.1.RELEASE</version> 
</dependency> 
<dependency> 
  <groupId>redis.clients</groupId> 
  <artifactId>jedis</artifactId> 
  <version>2.7.3</version> 
</dependency> 
  <!--Redis end --> 
2,설정 bean
application.xml 에 다음 설정 을 추가 합 니 다.

<!-- jedis    --> 
  <bean id="poolConfig" class="redis.clients.jedis.JedisPoolConfig" > 
     <property name="maxIdle" value="${redis.maxIdle}" /> 
     <property name="maxWaitMillis" value="${redis.maxWait}" /> 
     <property name="testOnBorrow" value="${redis.testOnBorrow}" /> 
  </bean > 
 <!-- redis      --> 
  <bean id="connectionFactory" class="org.springframework.data.redis.connection.jedis.JedisConnectionFactory" > 
     <property name="poolConfig" ref="poolConfig" /> 
     <property name="port" value="${redis.port}" /> 
     <property name="hostName" value="${redis.host}" /> 
     <property name="password" value="${redis.password}" /> 
     <property name="timeout" value="${redis.timeout}" ></property> 
  </bean > 
  <bean id="redisTemplate" class="org.springframework.data.redis.core.RedisTemplate" > 
     <property name="connectionFactory" ref="connectionFactory" /> 
     <property name="keySerializer" > 
       <bean class="org.springframework.data.redis.serializer.StringRedisSerializer" /> 
     </property> 
     <property name="valueSerializer" > 
       <bean class="org.springframework.data.redis.serializer.JdkSerializationRedisSerializer" /> 
     </property> 
  </bean > 
   
  <!-- cache   --> 
  <bean id="methodCacheInterceptor" class="com.mucfc.msm.common.MethodCacheInterceptor" > 
     <property name="redisUtil" ref="redisUtil" /> 
  </bean > 
  <bean id="redisUtil" class="com.mucfc.msm.common.RedisUtil" > 
     <property name="redisTemplate" ref="redisTemplate" /> 
  </bean > 
그 중에서 설정 파일 redis 일부 설정 데이터 redis.properties 는 다음 과 같 습 니 다.

#redis   
redis.host=10.75.202.11 
redis.port=6379 
redis.password=123456 
redis.maxIdle=100 
redis.maxActive=300 
redis.maxWait=1000 
redis.testOnBorrow=true 
redis.timeout=100000 
 
#           
targetNames=xxxRecordManager,xxxSetRecordManager,xxxStatisticsIdentificationManager 
#          
methodNames= 
 
#         
com.service.impl.xxxRecordManager= 60 
com.service.impl.xxxSetRecordManager= 60 
defaultCacheExpireTime=3600 
 
fep.local.cache.capacity =10000 
이 properties 파일 을 스 캔 하려 면 application.xml 에 다음 설정 을 추가 하 십시오.

 <!--   properties     -->  
 <bean id="propertyConfigurer" class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer"> 
  <property name="locations"> 
    <list> 
      <value>classpath:properties/*.properties</value> 
      <!--         ,            --> 
    </list> 
  </property> 
</bean> 
3.일부 도구 류
(1)RedisUtil
위의 bean 에서 RedisUtil 은 데 이 터 를 캐 시 하고 제거 하 는 인 스 턴 스 입 니 다.

package com.mucfc.msm.common; 
 
import java.io.Serializable; 
import java.util.Set; 
import java.util.concurrent.TimeUnit; 
 
import org.apache.log4j.Logger; 
import org.springframework.data.redis.core.RedisTemplate; 
import org.springframework.data.redis.core.ValueOperations; 
 
/** 
 * redis cache     
 * 
 */ 
public final class RedisUtil { 
  private Logger logger = Logger.getLogger(RedisUtil.class); 
  private RedisTemplate<Serializable, Object> redisTemplate; 
 
  /** 
   *        value 
   * 
   * @param keys 
   */ 
  public void remove(final String... keys) { 
    for (String key : keys) { 
      remove(key); 
    } 
  } 
 
  /** 
   *     key 
   * 
   * @param pattern 
   */ 
  public void removePattern(final String pattern) { 
    Set<Serializable> keys = redisTemplate.keys(pattern); 
    if (keys.size() > 0) 
      redisTemplate.delete(keys); 
  } 
 
  /** 
   *      value 
   * 
   * @param key 
   */ 
  public void remove(final String key) { 
    if (exists(key)) { 
      redisTemplate.delete(key); 
    } 
  } 
 
  /** 
   *            value 
   * 
   * @param key 
   * @return 
   */ 
  public boolean exists(final String key) { 
    return redisTemplate.hasKey(key); 
  } 
 
  /** 
   *      
   * 
   * @param key 
   * @return 
   */ 
  public Object get(final String key) { 
    Object result = null; 
    ValueOperations<Serializable, Object> operations = redisTemplate 
        .opsForValue(); 
    result = operations.get(key); 
    return result; 
  } 
 
  /** 
   *      
   * 
   * @param key 
   * @param value 
   * @return 
   */ 
  public boolean set(final String key, Object value) { 
    boolean result = false; 
    try { 
      ValueOperations<Serializable, Object> operations = redisTemplate 
          .opsForValue(); 
      operations.set(key, value); 
      result = true; 
    } catch (Exception e) { 
      e.printStackTrace(); 
    } 
    return result; 
  } 
 
  /** 
   *      
   * 
   * @param key 
   * @param value 
   * @return 
   */ 
  public boolean set(final String key, Object value, Long expireTime) { 
    boolean result = false; 
    try { 
      ValueOperations<Serializable, Object> operations = redisTemplate 
          .opsForValue(); 
      operations.set(key, value); 
      redisTemplate.expire(key, expireTime, TimeUnit.SECONDS); 
      result = true; 
    } catch (Exception e) { 
      e.printStackTrace(); 
    } 
    return result; 
  } 
 
  public void setRedisTemplate( 
      RedisTemplate<Serializable, Object> redisTemplate) { 
    this.redisTemplate = redisTemplate; 
  } 
} 
(2)MethodCacheInterceptor
절단면 MethodCache Interceptor,캐 시 에 데이터 가 존재 할 경우 캐 시 에서 데 이 터 를 가 져 오 는 방법 을 추가 하 는 데 사 용 됩 니 다.그렇지 않 으 면 처음으로 데이터베이스 에서 가 져 와 결 과 를 캐 시 에 저장 합 니 다.

package com.mucfc.msm.common; 
 
import java.io.File; 
import java.io.FileInputStream; 
import java.io.InputStream; 
import java.util.ArrayList; 
import java.util.List; 
import java.util.Properties; 
 
import org.aopalliance.intercept.MethodInterceptor; 
import org.aopalliance.intercept.MethodInvocation; 
import org.apache.log4j.Logger; 
 
 
public class MethodCacheInterceptor implements MethodInterceptor { 
  private Logger logger = Logger.getLogger(MethodCacheInterceptor.class); 
  private RedisUtil redisUtil; 
  private List<String> targetNamesList; //       service   
  private List<String> methodNamesList; //            
  private Long defaultCacheExpireTime; //           
  private Long xxxRecordManagerTime; // 
  private Long xxxSetRecordManagerTime; // 
 
  /** 
   *                      
   */ 
  public MethodCacheInterceptor() { 
    try { 
       File f = new File("D:\\lunaJee-workspace\\msm\\msm_core\\src\\main\\java\\com\\mucfc\\msm\\common\\cacheConf.properties");  
       //           ,         
       InputStream in = new FileInputStream(f);  
//     InputStream in = getClass().getClassLoader().getResourceAsStream( 
//         "D:\\lunaJee-workspace\\msm\\msm_core\\src\\main\\java\\com\\mucfc\\msm\\common\\cacheConf.properties"); 
      Properties p = new Properties(); 
      p.load(in); 
      //       
      String[] targetNames = p.getProperty("targetNames").split(","); 
      String[] methodNames = p.getProperty("methodNames").split(","); 
 
      //          
      defaultCacheExpireTime = Long.valueOf(p.getProperty("defaultCacheExpireTime")); 
      xxxRecordManagerTime = Long.valueOf(p.getProperty("com.service.impl.xxxRecordManager")); 
      xxxSetRecordManagerTime = Long.valueOf(p.getProperty("com.service.impl.xxxSetRecordManager")); 
      //   list 
      targetNamesList = new ArrayList<String>(targetNames.length); 
      methodNamesList = new ArrayList<String>(methodNames.length); 
      Integer maxLen = targetNames.length > methodNames.length ? targetNames.length 
          : methodNames.length; 
      //                 list  
      for (int i = 0; i < maxLen; i++) { 
        if (i < targetNames.length) { 
          targetNamesList.add(targetNames[i]); 
        } 
        if (i < methodNames.length) { 
          methodNamesList.add(methodNames[i]); 
        } 
      } 
    } catch (Exception e) { 
      e.printStackTrace(); 
    } 
  } 
 
  @Override 
  public Object invoke(MethodInvocation invocation) throws Throwable { 
    Object value = null; 
 
    String targetName = invocation.getThis().getClass().getName(); 
    String methodName = invocation.getMethod().getName(); 
    //          
    //if (!isAddCache(StringUtil.subStrForLastDot(targetName), methodName)) { 
    if (!isAddCache(targetName, methodName)) { 
      //          
      return invocation.proceed(); 
    } 
    Object[] arguments = invocation.getArguments(); 
    String key = getCacheKey(targetName, methodName, arguments); 
    System.out.println(key); 
 
    try { 
      //         
      if (redisUtil.exists(key)) { 
        return redisUtil.get(key); 
      } 
      //      
      value = invocation.proceed(); 
      if (value != null) { 
        final String tkey = key; 
        final Object tvalue = value; 
        new Thread(new Runnable() { 
          @Override 
          public void run() { 
            if (tkey.startsWith("com.service.impl.xxxRecordManager")) { 
              redisUtil.set(tkey, tvalue, xxxRecordManagerTime); 
            } else if (tkey.startsWith("com.service.impl.xxxSetRecordManager")) { 
              redisUtil.set(tkey, tvalue, xxxSetRecordManagerTime); 
            } else { 
              redisUtil.set(tkey, tvalue, defaultCacheExpireTime); 
            } 
          } 
        }).start(); 
      } 
    } catch (Exception e) { 
      e.printStackTrace(); 
      if (value == null) { 
        return invocation.proceed(); 
      } 
    } 
    return value; 
  } 
 
  /** 
   *        
   * 
   * @return 
   */ 
  private boolean isAddCache(String targetName, String methodName) { 
    boolean flag = true; 
    if (targetNamesList.contains(targetName) 
        || methodNamesList.contains(methodName)) { 
      flag = false; 
    } 
    return flag; 
  } 
 
  /** 
   *     key 
   * 
   * @param targetName 
   * @param methodName 
   * @param arguments 
   */ 
  private String getCacheKey(String targetName, String methodName, 
      Object[] arguments) { 
    StringBuffer sbu = new StringBuffer(); 
    sbu.append(targetName).append("_").append(methodName); 
    if ((arguments != null) && (arguments.length != 0)) { 
      for (int i = 0; i < arguments.length; i++) { 
        sbu.append("_").append(arguments[i]); 
      } 
    } 
    return sbu.toString(); 
  } 
 
  public void setRedisUtil(RedisUtil redisUtil) { 
    this.redisUtil = redisUtil; 
  } 
} 
4.캐 시가 필요 한 클래스 나 방법 설정
application.xml 에 다음 설정 을 추가 합 니 다.여러 종류 나 방법 으로 여러 개 를 설정 할 수 있 습 니 다.

<!--             --> 
<bean id="methodCachePointCut" class="org.springframework.aop.support.RegexpMethodPointcutAdvisor" > 
   <property name="advice" > 
     <ref local="methodCacheInterceptor" /> 
   </property> 
   <property name="patterns" > 
     <list> 
      <!--           --> 
       <value>com\.mucfc\.msm\.service\.impl\...*ServiceImpl.*</value > 
     </list> 
   </property> 
</bean > 
5.실행 결과:
간단 한 단원 테스트 는 다음 과 같다.

@Test 
public void getSettUnitBySettUnitIdTest() { 
  String systemId = "CES"; 
  String merchantId = "133"; 
  SettUnit configSettUnit = settUnitService.getSettUnitBySettUnitId(systemId, merchantId, "ESP"); 
  SettUnit configSettUnit1 = settUnitService.getSettUnitBySettUnitId(systemId, merchantId, "ESP"); 
  boolean flag= (configSettUnit == configSettUnit1); 
  System.out.println(configSettUnit); 
  logger.info("    " + configSettUnit.getBusinessType()); 
  
 // localSecondFIFOCache.put("configSettUnit", configSettUnit.getBusinessType()); 
 // String string = localSecondFIFOCache.get("configSettUnit"); 
   logger.info("    " + string); 
} 
이것 은 처음으로 단원 테스트 를 실행 하 는 과정 이다.
MethodCache Interceptor 클래스 에서 정지점 을 찍 은 다음 검색 할 때마다 이 방법 에 먼저 들 어 갑 니 다.

순서대로 실행 하면 캐 시가 없 기 때문에 데이터 베 이 스 를 직접 찾 습 니 다.

인쇄 된 SQL 문장:

두 번 째 실행:
처음 실 행 했 을 때 캐 시 에 기록 되 어 있 었 기 때 문 입 니 다.그래서 두 번 째 는 캐 시 에서 데 이 터 를 직접 가 져 옵 니 다.

3.두 번 의 결 과 를 취하 여 주소 의 대 비 를 한다.
두 사람 이 같은 대상 이 아니 라 는 것 을 발견 했다.맞 아,맞 아.ehcache 를 사용한다 면 두 사람의 메모리 주 소 는 같 을 것 입 니 다.그것 은 redis 와 ehcache 가 사용 하 는 캐 시 시스템 이 다 르 기 때문이다.ehcache 는 로 컬 컴퓨터 의 메모리 에 캐 시 를 사용 하기 때문에 캐 시 로 데 이 터 를 가 져 올 때 로 컬 컴퓨터 에서 직접 가 져 옵 니 다.자바 대상 으로 변환 하면 같은 메모리 주소 가 됩 니 다.redis 는 redis 서비스 가 설 치 된 컴퓨터(보통 다른 컴퓨터)이기 때문에 데 이 터 를 가 져 올 때 로 컬 로 전송 되 고 서로 다른 메모리 주소 에 대응 하기 때문에==으로 비교 하면 false 로 돌아 갑 니 다.하지만 캐 시 에서 가 져 온 것 이 확실 합 니 다.이 점 은 위의 정지점 에서 볼 수 있 습 니 다.

이상 은 본문의 전체 내용 이 므 로 여러분 의 학습 에 도움 이 되 기 를 바 랍 니 다.

좋은 웹페이지 즐겨찾기