-
Notifications
You must be signed in to change notification settings - Fork 1
Description
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 방식으로 백업 할 수 있다
- RDB (Redis Database) : 메모리에 있는 데이터 전체에서 스냅샷을 작성하고, 이를 디스크로 저장하는 방식
- 특정 시간마다 여러 개의 스냅샷을 생성하고, 데이터를 복원해야 한다면 스냅샷 파일을 그대로 로딩만 하면 됨.
- 하지만, 스냅샷 이후 변경된 데이터는 복구할 수 없음. → 데이터 유실(loss)
- 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 되었음
설정 순서
-
maven 설정
-
application.properties에 추가
-
host, port 설정
-
Redis Config 추가
-
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 클래스가 아닌경우에만 유형 정보를 추가하도록 지정하는 것이다.
Metadata
Metadata
Assignees
Labels
Type
Projects
Status