개발기술/데이터베이스

Redis (Redis작동법, Spring 연결)

bsh6226 2024. 8. 23. 11:35

레디스 

  • DB의 디스크가 아닌 메모리에 저장하여 휘발성이 있지만 영속성 기능을 지원하기도 함. 안정성이 비교적 떨어지기 때문에주로 캐시서버로 사용됨.
  • 인덱스방식이 아니라 key-value방식으로 저장
  • 다양한 방식의 데이터타입 적용가능 (hash나 list같은 데이터 저장가능)
  • tomcat과는 다르게 embedded방식이 아니라 OS내에 설치하여 별도의 서버로 동작한다.(micro service)

 

레디스 종류

싱글인스턴스방식 

센티넬, 클러스터방식 - 마스터 슬레이브 구조을 하여, 서버 한대가 죽더라도 다른 서버가 살아있으면 구동 가능하도록 구현

 

레디스 활용점

1. 캐쉬서버로서 DB로의 직접접근을 최소화시킴

2. 동기화 문제를 해결하기 위해서 DB의 Serializable을 대신해서 SpinLock을 구현

 

OS 내에 레디스 설치 및 운용

레디스 설치 : https://redis.io/docs/latest/operate/oss_and_stack/install/install-redis/install-redis-on-mac-os/

레디스 문서 : http://redisgate.kr/redis/introduction/redis_intro.php

 

맥의 경우 homebrew를 통해서 redis를 설치한 후에, Redis서버를 동작시켜놓아야 Spring이 Lettuce or Jedis 같은 Client를 통해서 redis전용 프로토콜을 사용하여 레디스 서버와 통신할 수 있다.

 

  • CLI를 통한 레디스 제어
    • redis-server : redis 서버동작
    • redis-cli : redis 서버에 접근
    • $> set myKey myValue : key - value pair를 저장함
    • $> gey myKey : key를 통해 value를 찾음
    • $> del myKey : key를 통해 key-value pair를 제거함
    • $> keys * : 모든
    • 레디스를 CLI를 통해서 동작시키면 CMD창이 꺼지면 같이 꺼지기때문에 brew를 통해서 실행 및 종료를 시켜야함.
      • brew services start redis
      • brew services stop redis
    • 레디스 환경설정
      • vi /user/local/etc/redis.conf : Redis환경설정 변경을 위해서 파일 열기
        • /requirepass : 'requirepass'키워드로 문서를 검색하여 'foobared'로 표기된 password 설정위치 확인
        • /port : 'port'키워드로 검색하여 6379로 설정되어있는 값을 변경가능
      • redis-server /user/local/etc/redis.conf : 변경된 환경설정으로 서버실행

 

 

Spring을 통한 레디스 연결

1. Gradle Implementation

implementation 'org.springframework.boot:spring-boot-starter-data-redis'

 

2. 설정값 셋팅

data:
  redis:
    host: localhost
    port : 6379

 

3. Spring Configuration

 

@EnableCaching을 통해서 Caching관련된 annotation을 자동으로 Scan 하도록 설정한다.

@SpringBootApplication
@EnableCaching
public class ZerobaseReservationApplication {
    public static void main(String[] args) {
        SpringApplication.run(ZerobaseReservationApplication.class, args);
    }
}

 

4. Bean 등록

레디스를 동작시키기 위해서는 대표적으로 세가지 객체가 필요하다. 1. ReddisConnectionFactory 2. ReddisTemplate 3. ReddisCacheManager

  •  ReddisConnectionFactory : IP와 Port를 설정하여 Lettuce/Jedis와 같은 Client API를 통해서 Redis와 전용 프로토콜로 통신하도록 연결을 지원한다. 해당 객체는 ReddisTemplate 혹은 CacheManager 내부에서 사용된다.
  • RedisTemplate : Redis를 직접적으로 조작하는데 사용되며, Key-value 등록 등 보다 구체적인 조작을 가능하도록 한다. 주로 단순 캐슁 작업보다는 transactions, Lua scripting, or pub/sub 등의 레디스 기능들을 직접적으로 사용하고자 할때 사용된다. 
  • ReddisCacheManager : cache annotation과 내부적으로 Redistemplate을 사용하여 추상화된 방식으로 캐슁작업을 지원한다. 
@RequiredArgsConstructor
@Configuration
public class CacheConfig {
    @Value("${spring.redis.host}")
    private String host;

    @Value("${spring.redis.port}")
    private String port;

    @Bean // redis와 connection을 맺는 bean을 생성
    public RedisConnectionFactory redisConnectionFactory() {
        RedisStandaloneConfiguration conf = new RedisStandaloneConfiguration();
        /* 클러스터 환경으로 설정할 경우 아래의 설정값 사용
        RedisClusterConfiguration redisClusterConfiguration =
         new RedisClusterConfiguration();
         */
        conf.setHostName(host);
        conf.setPort(Integer.parseInt(port));
        // conf.setPassword(); password설정필요시 사용
        return new LettuceConnectionFactory(conf);
    }

    @Bean // redis Connection을 캐쉬에 적용할 수 있는 bean을 생성
    public CacheManager redisCacheManager(RedisConnectionFactory redisConnectionFactory) {
        RedisCacheConfiguration conf = RedisCacheConfiguration.defaultCacheConfig()
                .serializeKeysWith(RedisSerializationContext.SerializationPair.fromSerializer(new StringRedisSerializer()))
                .serializeValuesWith(RedisSerializationContext.SerializationPair.fromSerializer(new GenericJackson2JsonRedisSerializer()));

        return RedisCacheManager.RedisCacheManagerBuilder
                .fromConnectionFactory(redisConnectionFactory)
                .cacheDefaults(conf)
                .build();
    }
}

 

4. 원하는 메소드에 캐쉬 적용하기 : @Cacheable(key : inputParameter, value) ; value값은 redis data의 prefix로 사용됨

 

 

@Cacheable(key = "#companyName", value = "finance")
public ScrapedResult getDividendByCompanyName(String companyName) {

 

5. 캐쉬를 적용하기 위해서 Serialization 에러 해결하기 ; config에서 cover못한 serialization 과정을 별도로 정정

public class DividendInfo {
    @JsonSerialize(using = LocalDateTimeSerializer.class)
    @JsonDeserialize(using = LocalDateTimeDeserializer.class)
    private LocalDateTime date;

 

6.  캐쉬삭제

  • Config에서 TTL(Time to Live; 유효기간)을 설정하여 삭제주기 설정 ; 특정 prefix value값에 대해서만 적용하도록 설정가능
public CacheManager redisCacheManager(RedisConnectionFactory redisConnectionFactory) {
    RedisCacheConfiguration conf = RedisCacheConfiguration.defaultCacheConfig()
            .serializeKeysWith(RedisSerializationContext.SerializationPair.fromSerializer(new StringRedisSerializer()))
            .serializeValuesWith(RedisSerializationContext.SerializationPair.fromSerializer(new GenericJackson2JsonRedisSerializer()))
            .entryTtl(Duration.ofDays(1));

 

  • Scheduler를 사용하여 캐쉬삭제 로직 생성 ; 특정 prefix value값에 대해서만 적용하도록 설정
@CacheEvict(value = CacheKey.KEY_FINANCE, allEntries = true)
@Scheduled(cron = "${scheduler.scrap.yahoo}")
public void yahooFinanceScheduling() {

 

스프링 레디스 객체  : ReddisCacheManager

Annotation

  • @Cacheable: method의 결과값을 캐싱함. 동일한 argument로 method call이 이루어졌을때, 캐싱한 값을 return함.
  • @CachePut: method의 결과값을 캐싱함. 동일한 argument로 method call이 이루어진것과 관계없이 항상 캐싱하여 refresh함. 신규로 데이터가 들어오거나 update되는 메소드에 유용함.
  • @CacheEvict: method의 argument가 들어오면 해당 argument에 해당하는 캐쉬값을 삭제함.

 

TTL