728x90

 

Pub/Sub은 자주 사용되는 시스템 디자인 패턴 중 하나이다.
Redis는 메시지 브로커 역할을 하며, Publisher가 발행하는 메시지를 Subscriber에게 전달한다.

실시간 애플리케이션, 채팅 시스템, 알림 등을 빌드하기 위한 강력한 기능이다. 인메모리의 장점을 가지고 있어 빠른 처리가 가능하지만, 단점 또한 존재해 kafka등의 시스템을 사용하는 것도 고려해야 할 필요가 있다.

 

코드로 구현

@Service
@Slf4j
public class MessageListenerService implements MessageListener {
    @Override
    public void onMessage(Message message, byte[] pattern) {
      log.info("Received Channel: {} Channel: {}" , new String(message.getChannel()), new String(message.getBody()));

    }
}

 

메세지를 받는 서비스를 MessageListener 인터페이스를 통해 Redis의 "chat" 채널에서 발생하는 메시지를 수신하고,
onMessage메서드를 통해 수신된 메시지와 채널 정보를 로깅하는 간단한 Pub/Sub 시스템을 구현했습니다.

 

@Component
public class RedisConfig {

    @Bean
    MessageListenerAdapter messageListenerAdapter() {
        return new MessageListenerAdapter(new MessageListenerService());
    }

    @Bean
    RedisMessageListenerContainer redisMessageListenerContainer(RedisConnectionFactory connectionFactory, MessageListenerAdapter listener) {
        RedisMessageListenerContainer container = new RedisMessageListenerContainer();
        container.setConnectionFactory(connectionFactory);
        container.addMessageListener(listener, ChannelTopic.of("chat"));
        return container;
    }

 

  • RedisConnectionFactory는 Redis와의 연결을 나타내는 Spring의 빈입니다.
  • MessageListenerAdapter는 실제 메시지를 처리할 리스너입니다.
  • ChannelTopic.of("chat")는 구독할 Redis 채널을 지정합니다. 위 코드에서는 "chat" 채널에 대한 리스너가 등록되어 있습니다.

API로 메시지 전달

@RestController
@RequiredArgsConstructor
public class PublishController {
    
    private final RedisTemplate<String, String> redisTemplate;
    
    @PostMapping("/publish")
    public void publish(String message) {
        redisTemplate.convertAndSend("chat", message);
    }
}

 

RedisTemplate을 주입받아 메시지를 발행하는 API를 구현했습니다.

'DB(MySQL, MongoDB, Redis, Kafka) > Redis' 카테고리의 다른 글

Spring Boot에서 Redis Cache 사용  (0) 2024.01.06
Redis 데이터 타입과 기본 명령어  (0) 2024.01.05
Redis 기본 개념  (1) 2024.01.05
728x90

들어가며,

앞서 Redis에 대한 개념과 기본 명령어를 통해 CLI 환경에서 Redis를 사용했다.

이제 본격적으로 Redis의 캐싱, 세션, pub sub 등에 대해 공부할 예정이다.

캐싱

2024.01.05 - [DB(MySQL, MongoDB, Redis, Kafka)/Redis] - Redis 기본 개념

기본 개념에서 공부했듯이 Redis는 인메모리 데이터베이스로 디스크에 저장하고 읽어 오는데 드는 비용을 줄이고 속도를 빠르게 하기 위해 사용된다. 

이때 사용되는 기능이 Cache이다. 

  1. 캐시 내부를 확인
  2. 없으면, 데이터베이스를 확인
  3. 캐시에 데이터를 저장

이 구조로 사용된다. 그러나 메모리는 휘발성이 높은 단점이 있었는데, 캐시에 저장된 데이터는 정책상 정해놓은 시간이 소요되면 자동으로 삭제된다.

초기 yml 설정

spring:
  data:
    redis:
      host: 127.0.0.1
      port: 6379
  datasource:
    url: jdbc:mysql://127.0.0.1:3306/redis?useUnicode=true&characterEncoding=utf-8&useSSL=false&serverTimezone=UTC
    username: root
    password: 1234
  jpa:
    hibernate:
      ddl-auto: create
    show-sql: true

 

redis에 대한 설정, Mysql에 대한 설정 이렇게 두가지를 먼저 설정하는 것이 중요하다.
redis와 Mysql은 모두 docker로 컨테이너에서 띄워 사용.

 

캐시를 적용하기 위한 간단한 회원 로직 작성

 

Repository에서 Jpa연동을 설정하고 Service에서 다시 Jpa 기본 메서드인 findById를 통해 id값으로 조회하는 로직을 작성한다.
Controller는 HTTP GET 요청에 따라 동작한다.
코드는 간단한 구현이라 생략합니다.

 

Redis Config 설정

@Configuration
public class RedisConfig {

    @Bean
    RedisTemplate<String, Member> memberRedisTemplate(RedisConnectionFactory connectionFactory) {
        var objectMapper = new ObjectMapper()
                .configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false)
                .registerModule(new JavaTimeModule())
                .disable(SerializationFeature.WRITE_DATE_KEYS_AS_TIMESTAMPS);

        var template = new RedisTemplate<String, Member>();
        template.setConnectionFactory(connectionFactory);
        template.setKeySerializer(new StringRedisSerializer());
        template.setValueSerializer(new Jackson2JsonRedisSerializer<>(objectMapper, Member.class));
        return template;
    }
}

 

RedisTemplate을 사용하기 위해 config 클래스를 만들었다. 이 RedisTemplate은 문자열 키와 Member객체로 이루어진다.

RedisConnectionFactory를 통해 Redis서버와 연결을 돕는다. 여기에는 Lettuce 또는 Jedis 등이 있다. 
Key와 Value를 설정하는데, Value에 들어가는 Member 객체를 Json으로 받기 위해 Jackson2JsonRedisSerializer를 사용한다. (몇가지 오류를 방지하기 위해 objectMapper를 따로 위에서 만들어 둠)

 

public Member getMember(Long id) {
    var key = "member:" + id;

    var cacheMember = redisTemplate.opsForValue().get(key);
    if (cacheMember != null) {
        return cacheMember;
    }
    Member member = memberRepository.findById(id).orElseThrow();
    redisTemplate.opsForValue().set(key, member);
    return member;

}

 

다시 Service 계층으로 돌아와 Template을 활용해 아래의 로직을 작성하면 된다.

캐시 내부를 확인 -> 없으면, 데이터베이스를 확인 -> 캐시에 데이터를 저장

 

 

'DB(MySQL, MongoDB, Redis, Kafka) > Redis' 카테고리의 다른 글

Redis Pub/ Sub  (0) 2024.01.10
Redis 데이터 타입과 기본 명령어  (0) 2024.01.05
Redis 기본 개념  (1) 2024.01.05
728x90

키-밸류 스토어

Redis는 고성능의 키-밸류 스토어로, 주로 데이터베이스의 캐시로 사용됩니다. 이를 통해 데이터베이스 조회 시간을 단축시키고, 시스템 전반의 성능을 향상시킬 수 있습니다.

  • Cache Aside 패턴: 클라이언트가 데이터를 요청하면, 먼저 Redis 캐시에서 데이터의 존재 유무를 확인합니다. 캐시에 데이터가 있다면 (Cache Hit) 캐시의 데이터를 사용하고, 없다면 (Cache Miss) 실제 데이터베이스에서 데이터를 가져와 캐시에 저장한 후 클라이언트에 반환합니다.
  • Write Back 패턴: 데이터베이스에 쓰기 작업이 많은 경우, 캐시에 데이터를 먼저 저장하고 주기적으로 데이터베이스에 배치로 업데이트하여 성능을 향상시킵니다.

String 타입

기본적인 데이터 타입으로, 최대 크기는 512MB입니다. text, byte를 저장, 원자적 연산 기능을 하며, 아래 명령어를 통해 조작 가능합니다.

  • SET
  • SETNX
  • GET
  • MGET
  • INC
  • DEC

List and Set

  • Lists: Linked-list 형태로, 데이터 추가 및 삭제가 빠릅니다. lrange, lpush, rpush 등의 명령어를 사용합니다.
  • Sets: 중복을 허용하지 않는 유니크한 값의 집합입니다. sadd, smembers 등의 명령어를 사용합니다.

  • PUSH
  • POP

push와 pop을 통해 값을 삽입하고 추출한다. stack의 경우 가장 최근에 넣은 값부터 반출되지만, queue는 가장 처음에 넣은 값부터 순서대로 반출되는 차이를 가진다.

Hash

Hashes: 하나의 키 아래 여러 개의 필드-값 쌍을 저장합니다.

  • HSET
  • HGET
  • HGETALL

Sorted Set

Sorted Sets: 유니크한 값의 집합이며, 각 값은 연관된 점수로 정렬됩니다.

  • ZADD
  • ZREM
  • ZRANGE
  • ZCARD
  • ZRANK

세션 스토어

  • 세션 불일치 문제: 여러 서버를 운영할 때, 클라이언트의 세션이 서버마다 다를 수 있는 문제가 발생할 수 있습니다.
  • Redis 세션 스토어 사용: Redis를 사용하여 여러 서버 환경에서도 세션 데이터를 일관성 있게 관리할 수 있습니다. 이를 위해 connect-redis와 같은 라이브러리를 사용하여 Express와 Redis를 연결할 수 있습니다

 

'DB(MySQL, MongoDB, Redis, Kafka) > Redis' 카테고리의 다른 글

Redis Pub/ Sub  (0) 2024.01.10
Spring Boot에서 Redis Cache 사용  (0) 2024.01.06
Redis 기본 개념  (1) 2024.01.05
728x90

in-memory DB

인메모리 데이터베이스란 디스크가 아닌 메모리에 데이터를 저장해서 사용한다는 의미다.

특징은 크게 3가지가 있다.

  • 빠른 속도 
  • 휘발성
  • 다양한 자료구조

ACID 원칙은?

  • 원자성
  • 일관성
  • 고립성
  • 내구성

데이터베이스가 가져야할 4가지 원칙에서 인메모리 데이터베이스는 위 3가지는 지켜지지만, 휘발성이라는 특성으로 인해 내구성을 지키기 어렵다. 따라서 추가적인 조치가 필요하며, 이에 따른 방법은 스냅샷, 트랜잭션 로깅, NVRAM 등이 있다.

 

Redis

Redis는 캐싱, 메시지 브로커 역할을 하는 오픈소스 형태의 인메모리 데이터베이스다.
하지만, 이것은 기존의 디스크 저장 방식의 데이터 베이스가 필요하지 않는 상황에서 사용된다.
디스크가 아닌 메모리에 데이터를 읽고 쓰기 때문에 매우 빠른 성능을 제공한다.

 

Redis 역시 앞서 말한 인메모리 DB의 약점인, 데이터 손실, 내구성이 약하다는 단점을 가지고 있다. 이를 해결하기 위해 Persistence기능을 제공한다. 이 기능을 통해 충격을 받거나 다운될 때 디스크에 데이터를 저장하고 복원할 수 있도록 한다.

Redis persistence 기능은 몇가지 방법이 있다. 

  • 스냅샷
  • AOF

다만, 스냅샷은 스냅샷 간의 충돌에서 데이터 손실이 일어날 수 있고, AOF는 스냅샷에 비해 느려지는 속도와 리소스를 많이 사용하는 단점이 있다

 

Redis의 형태

 

Redis는 key - Value 형태로 구성되며, 다양한 자료구조를 개발자가 활용할 수 있도록 도와준다.

위 그림에서도 보이듯이, 해시 테이블을 구현하여 고유한 키와 데이터 값에 대한 포인터를 저장하는 Nosql 데이터베이스 유형이다. 

 

다른 데이터베이스와의 차이

특징/
유형
관계형 데이터베이스 그래프 데이터베이스 문서 데이터베이스 키-값 데이터베이스
데이터 모델 테이블(관계형) 그래프 문서(반구조화) 키-값 쌍
데이터 관계 복잡한 관계 지원 그래프 구조 내 관계 지원 문서 내에 중첩된 데이터 지원 독립된 키-값 쌍, 관계 없음
쿼리
언어
SQL 그래프 쿼리 언어 풍부한 쿼리 언어 (JSON 쿼리) key 로만 데이터 액세스
성능 복잡한 쿼리 및 JOIN 수행 가능 관계 트리버스 및 관계 쿼리에 특화 유연한 데이터 모델과 쿼리 가능 뛰어난 성능, 단순한 구조
사용
사례
구조화된 데이터 및 관계가 필요한 경우 네트워크, 추천, 사회적 관계에 중점 반구조화되거나 반-정형 데이터 관리 단순한 키-값 쌍 저장에 중점
확장성 일반적으로 수직적 확장 일반적으로 수직적 및 수평적 확장 일반적으로 수직적 및 수평적 확장 수평적 확장에 적합
고가용성 복제 및 클러스터링으로 고가용성 보장 높은 연결성과 데이터 모델에 기반한 고가용성 복제 및 샤딩을 통한 고가용성 복제 및 클러스터링으로 고가용성 보장

 

'DB(MySQL, MongoDB, Redis, Kafka) > Redis' 카테고리의 다른 글

Redis Pub/ Sub  (0) 2024.01.10
Spring Boot에서 Redis Cache 사용  (0) 2024.01.06
Redis 데이터 타입과 기본 명령어  (0) 2024.01.05

+ Recent posts