Redis

  • key-value 구조의 인메모리 데이터베이스
  • Redis 특징
    • Collection(List, Set, SortedSet, Hash) 지원
    • 싱글 쓰레드로 Race Condition 방지
  • 활용방안
    • 캐싱, 세션 저장, 메시지 큐, 실시간채팅, 랭킹, 분산락

Spring에서 Redis Client로 JedisLettuce가 있다
Redis Client로 성능상 우위에 있는 Lettuce를 사용할 것이다

Redis 로컬 초기 셋팅

  • docker 컨테이너로 Redis 실행
$ docker run -p 6379:6379 --name redis -d redis
$ docker exec -it redis /bin/bash
$ redis-cli

Config

implementation 'org.springframework.boot:spring-boot-starter-data-redis'
@RequiredArgsConstructor
@Configuration
// @EnableRedisRepositories         // Redis Repository 활성화
public class RedisRepositoryConfig {

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

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

    // Lettuce 사용
    @Bean
    public RedisConnectionFactory redisConnectionFactory() {
        return new LettuceConnectionFactory(host, port);
    }

    @Bean
    public RedisTemplate<String, Object> redisTemplate() {      // serializer 설정
        RedisTemplate<String, Object> redisTemplate = new RedisTemplate<>();
        redisTemplate.setConnectionFactory(redisConnectionFactory());
        redisTemplate.setKeySerializer(new StringRedisSerializer());
        redisTemplate.setValueSerializer(new StringRedisSerializer());
        // redisTemplate.setDefaultSerializer(new StringRedisSerializer());
        return redisTemplate;
    }
}

  • 캐시 어노테이션(레디스 추상화)을 사용하면 CacheManager를 사용하기 때문에 RedisTemplate을 Bean으로 등록할 필요가 없어진다

spring-data-redis는 접근방식으로 2가지를 제공한다.

1. RedisTemplate

  • 자료구조 기반으로 Redis를 사용
  • 자료구조별 Method
Method Description
opsForValue() String Interface
opsForList() List Interface
opsForSet() Set Interface
opsForZSet() SortedSet Interface
opsForHash() Hash Interface

image

@RequiredArgsConstructor
@Component
public class RedisComponent {
    private final RedisTemplate<String, Object> redisTemplate;

    public void set(final String key, final String value) {
        return redisTemplate.opsForValue().set(key, value);
    }

    public void get(final String key) {
        return redisTemplate.opsForValue().get(key);
    }
}

2. RedisRepository

  • 객체 기반으로 Redis를 사용
@Getter
@Setter
@RedisHash(value = "member", timeToLive = 3600)        // redis key prefix
public class Member {

    @Id
    private String id;      // id역할을 할 필드
    private String name;
    private int age;

    public Member(String name, int age) {
        this.name = name;
        this.age = age;
    }
}
public interface MemberRedisRepository extends CrudRepository<Member, String> {}

Cache Annotation

  • Spring은 AOP 방식으로 어노테이션 기반의 캐시추상화룰 제공하고 있다
  • 메서드 결과를 캐싱하여 사용한다
  • 캐시 어노테이션은 CacheManager를 통해 캐시를 사용한다
org.springframework.cache.Cache
org.springframework.cache.CacheManager
  • 캐시 추상화 활성화
@EnableCaching      // 캐시 활성화
@Configuration 
public class CacheConfig {
    ... 
}

1. @Cacheable

  • 캐시 저장 및 조회를 위한 어노테이션
  • 메서드 실행시 캐시가 없을 경우 로직을 실행 후 캐시로 저장하고 캐시가 있을 경우 저장된 캐시를 조회한다
@Cacheable("bestSeller")      // 캐시이름 : bestSeller, 캐시키 : bookNo
public Book getBestSeller(String bookNo) {
    ...
}
  • 캐시 키 값을 property로 직접 지정해서 저장할 수도 있다
@Cacheable(value = "bestSeller", key = "#bookNo")
public Book getBestSeller(String bookNo, User user, Date dateTime) {
    ...
}    
  • 캐시를 저장할 조건을 지정할 수도 있다
@Cacheable(value = "bestSeller", key = "#bookNo", condition = "#bookNo > 5")
public Book getBestSeller(String bookNo, User user, Date dateTime) {
    ...
}

2. @CachePut

  • 캐시 저장만을 위한 어노테이션
  • @Cacheable와 유사하게 캐시를 저장하지만 조회 시에는 저장된 캐시를 사용하지 않고 항상 메서드 로직을 실행한다

3. @CacheEvict

  • 캐시 삭제를 위한 어노테이션
  • 메서드 실행시 캐시를 제거한다
@CacheEvict(value = "bestSeller")
public void clearBestSeller() {}

Spring 공식 문서