Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Redis #228

Open
hyeonjaez opened this issue Apr 3, 2024 · 0 comments
Open

Redis #228

hyeonjaez opened this issue Apr 3, 2024 · 0 comments
Assignees
Labels
technical 기술 문서 작성

Comments

@hyeonjaez
Copy link
Member

Redis

캐시


  • 자주 사용하는 데이터를 미리 보관해둔 임시 장소를 의미
  • 비교적 저장 공간이 적고 전체적인 비용이 비쌈
  • 빠른 IO를 통해 성능적 이점을 가져올 수 있음

도중에 변경 될 일이 없는 데이터베이스 조회 값
자주 호출되는 데이터

스프링 부트에서의 캐시


  • 스프링 부트에서 사용할 수 있는 캐시는 대부분 JSR-107을 따름

JSR

  • Java Specification Requests의 줄임말로 자바 플랫폼에 대한 규격을 제안하거나 기술 한 것을 의미
  • JSR-107은 JCACHE(Java Temporary Caching API)에 관한 내용임
  • 자바의 기술적인 기능의 스펙을 정의하는데에 있어서 JSR-107은 자바 캐시에 대한 api 내용을 기술한 것
  • JSR-107이 추상화한 기능을 그대로 사용할 수 있다
  • JSR-107을 따르는 캐시를 사용하면 어떤 구현체 캐시를 사용하는지에 관계없이 추상화를 지원

로컬 캐시


  • 로컬(해당 서버)에서만 사용하는 캐시
  • 외부 서버와 트랜잭션 비용이 들지 않아 속도가 빠름
  • 로컬에서만 사용하기 때문에 분산 서버(로드밸런싱환경)의 구조에서 캐시를 공유하기 어려움
  • 클러스터링을 한다던가 해결할수는 있음

글로벌 캐시


  • 여러 서버에서 접근 할 수 있는 캐시 서버를 구축하여 사용하는 방식
  • 네트워크를 통해 데이터를 가져오는 트랜잭션 비용이 있어 로컬에 비해 상대적으로 느림
  • 별도의 서버로 운영되어 서버간 데이터 공유에 용이하다

Redis


  • Remote Dictionary Server 로 키 - 값 구조의 데이터를 저장하고 관리하기 위한 오픈소스 기반의 비관계형 데이터 관리 시스템

특징


  • 인 메모리 데이터 구조 -> 메모리를 사용함
  • 견고하다
  • 확장성
  • 클러스터링

백업


  • 메모리에 데이터를 관리하여 매우 빠른 속도로 데이터를 저장 및 조회 할 수 있다
  • 메모리 특성상 저장된 데이터는 휘발성이 있어서 레디스는 관리하고 있는 데이터에 영속성을 제공한다
  • 메모리에 있는 데이터를 디스크에 백업하는 기능을 제공하고 RDB 방식이나, AOF 방식으로 백업 할 수 있다
  1. RDB (Redis Database) : 메모리에 있는 데이터 전체에서 스냅샷을 작성하고, 이를 디스크로 저장하는 방식
  • 특정 시간마다 여러 개의 스냅샷을 생성하고, 데이터를 복원해야 한다면 스냅샷 파일을 그대로 로딩만 하면 됨.
  • 하지만, 스냅샷 이후 변경된 데이터는 복구할 수 없음. → 데이터 유실(loss)
  1. AOF (Append Only File) : 데이터가 변경되는 이벤트가 발생하면 이를 모두 로그에 저장하는 방식
  • 데이터를 생성, 수정, 삭제하는 이벤트를 초 단위로 취합 및 로그 파일에 작성
  • 모든 데이터의 변경 기록들을 보관하고 있으므로 최신 데이터 정보를 백업 가능
  • RDB 방식에 비해 데이터 유실량이 적음(초 단위 데이터는 유실 가능).
  • RDB 방식보다 로딩 속도가 느리고 와 파일 크기가 큰 것이 단점

⇒ 일부 데이터 손실에 영향을 받지 않는 경우(캐시로만 사용할 때), RDB

⇒ 장애 상황 직전까지의 모든 데이터가 보장되어야 할 경우, AOF

⇒ 강력한 내구성이 필요한 경우, RDB + AOF

⇒ 레디스는 일반적으로 AOF와 RDB를 동시에 사용하여 데이터를 백업한다.

  • 예를 들면, 매일 7시마다 RDB 스냅샷을 생성하고, RDB 생성 이후에 변경되는 데이터는 AOF로 백업.

스프링부트 redis


  • java 에서 사용하는 Redis client는 크게 2개가 있다 (Jedis, Lettuce)
  • 스프링 부트 2.0 이후로는 기본 클라이언트로 Lettuce가 사용됨 -> Jedis는 Deprecate 되었음

설정 순서

  1. maven 설정

  2. application.properties에 추가

  3. host, port 설정

  4. Redis Config 추가

  5. RedisConnectionFactory 빈으로 등록

실습


  • maven dependency 추가
<dependency>  
    <groupId>org.springframework.boot</groupId>  
    <artifactId>spring-boot-starter-data-redis</artifactId>  
</dependency>
  • Redis config
@Bean  
public RedisConnectionFactory redisConnectionFactory() {  
    RedisStandaloneConfiguration redisStandaloneConfiguration  
            = new RedisStandaloneConfiguration();  
    redisStandaloneConfiguration.setHostName(redisProperties.getHost());  
    redisStandaloneConfiguration.setPort(redisProperties.getPort());  
    redisStandaloneConfiguration.setPassword(redisProperties.getPassword());  
    redisStandaloneConfiguration.setDatabase(redisProperties.getDatabase());  
  
    return new LettuceConnectionFactory(redisStandaloneConfiguration);  
}
  • RedisStandaloneConfiguration : Redis 단독 구성을 나타냅니다. 호스트, 포트, 비밀번호, 데이터베이스 등의 설정을 관리한다.

  • Lettuce는 Redis를 위한 자바 기반 비동기 클라이언트 라이브러리로, 높은 성능과 확장성을 제공한다.

  • Spring Data Redis는 다양한 Redis 클라이언트 라이브러리를 지원하며, 그 중 하나로 Lettuce를 사용할 수 있다.

  • LettuceConnectionFactory는 RedisConnectionFactory 인터페이스를 구현하고 있다.

  • RedisConnectionFactory 인터페이스는 Spring Data Redis 에서 사용하는 추상화된 연결 팩토리입니다.

  • LettuceConnectionFactory를 사용하여 Redis 서버와의 연결을 설정을 한다.

  • RedisTemplate

@Bean  
public <T> RedisTemplate<String, T> redisTemplate() {  
    RedisTemplate<String, T> redisTemplate = new RedisTemplate<>();  
  
    redisTemplate.setKeySerializer(new StringRedisSerializer());  
    redisTemplate.setValueSerializer(new GenericJackson2JsonRedisSerializer());  
    redisTemplate.setHashKeySerializer(new StringRedisSerializer());  
    redisTemplate.setConnectionFactory(redisConnectionFactory());  
  
    return redisTemplate;  
}
  • RedisTemplate는 Spring Boot 에서 Redis와 상호 작용하는데 사용된다.

  • redisTemplate.setKeySerializer(new StringRedisSerializer()); ->

    • redis의 키는 문자열로 저장된다 그래서 키의 직렬화 방식을 StringRedisSerializer로 설정함
  • redisTemplate.setValueSerializer(new GenericJackson2JsonRedisSerializer());

    • value 값은 일반적으로 Json 형식으로 저장된닫 그래서 value의 직렬화 방식을 GenericJackson2JsonRedisSerializer로 설정한다
  • redisTemplate.setHashKeySerializer(new StringRedisSerializer());

    • Redis에서 Hash를 사용할때 Hash의 키도 문자열로 저장된다
  • redisTemplate.setConnectionFactory(redisConnectionFactory());

    • Redis와 연결을 관리하는 RedisConnectionFactory를 설정한다

redis에 객체(dto) 를 저장할때


  • serializer를 통해 직렬화 해주어야 한다.
  • 직렬화 방법은 3가지 있다.

1. Jackson2JsonRedisSerializer

  • Class Type를 지정 해야 하고 객체를 저장할 때 class 값 대신에 Class Type 값을 JSON 형태로 저장한다.
  • Class Type 값을 저장하여 package 등의 정보 일치를 고려할 필요가 없다.
  • 하지만 Class Type 을 지정해야 하기 때문에 특정 클래스에 종속적이다.
  • redisTemplate을 여러 쓰레드에서 접근하게 될때 serializer 타입의 문제가 발생하는 경우가 발생함

2. StringRedisSerializer

  • StringRedisSerializer는 String 값을 그대로 저장함
  • JSON 형태로 직접 encoding, decoding 을 해줘야 한다는 단점이 있다
  • 하지만 다른 방법의 serializer에서 발생할 수 있는 문제가 발생하지 않는다
  • class 타입을 지정할 필요 없음
  • 쓰레드간의 문제가 발생하지 않는다

3. GenericJackson2JsonRedisSerializer

  • 객체의 클래스 지정 없이  모든 Class Type을 JSON 형태로 저장할 수 있는 Serializer이다
  • Class Type 에 관계 없이 모든 객체를 직렬화 해준다는 장점이 있다
  • Object의 class 및 package 까지 전부 함께 저장하게 되어 다른 프로젝트에서 redis에 저장되어 있는 값을 사용하려면 package까지 일치시켜줘야한다
  • 따라서 MSA 구조와 같은 프로젝트에 문제가 생길 수 있다

하지만!

GenericJackson2JsonRedisSerializer가 custom한 ObjectMapper를 사용할 때는 다르다?

Object mapper는 기본적으로 직렬화/ 역직렬화 시 class type 정보를 포함하지 않기 때문에
직려화된 데이터는 type 정보가 존재하지 않는다

역직렬화 시에도 objectMapper가 type 정보를 모른 채 역직렬화를 진행하게 되고 기본 타입인 LinkedHashMap 으로 역직렬화 된다.

ObjectMapper에 activeDefaultTyping() 을 통하여 class type 을 함께 직렬화/역직렬화 하도록 설정해야한다.

ObjectMapper.DefaultTyping.NON_FINAL -> 객체의 유형 정보를 추가하되 final 클래스가 아닌경우에만 유형 정보를 추가하도록 지정하는 것이다.

@hyeonjaez hyeonjaez added the technical 기술 문서 작성 label Apr 3, 2024
@hyeonjaez hyeonjaez self-assigned this Apr 3, 2024
@hyeonjaez hyeonjaez moved this to Done in My-Books-project Apr 3, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
technical 기술 문서 작성
Projects
Status: Done
Development

No branches or pull requests

1 participant