본문 바로가기

Project

Redis ) Keyspace Notifications에 대한 궁금증 및 내가 사용했던 방법

Keyspace Notifications란?

특정 키에 대해 변경 사항(예: 만료, 삭제, 수정 등)이 발생했을 때 알림을 제공하는 기능

 

Keyspace Notifications 사용 방법

기본적으로 비활성화되어 있습니다.

-> 활성화하려면 Redis 설정 파일(redis.conf) 수정 or Redis CLI를 사용하여 설정.

  • Redis 설정에서 활성화
    • redis.conf 파일에서 다음과 같이 설정합니다:
    • notify-keyspace-events Ex
notify-keyspace-events Ex
  • CLI를 통해 활성화
    • Redis CLI에서 동적으로 설정
    • 여기서 Ex는 이벤트 유형을 나타냅니다:
      1. E: 일반 이벤트
      2. x: 만료(expired) 이벤트
CONFIG SET notify-keyspace-events Ex

 

Keyspace Notifications 이벤트 구독

Keyspace Notifications는 Redis의 Pub/Sub 채널을 통해 알림을 전송합니다.

  • 구독 채널 형식
    • 만료 이벤트의 채널은 다음과 같은 형식을 가집니다:
    • 기본적으로 Redis는 0~ 15로 16개를 할
__keyevent@<DB번호>__:expired
  • 구독 명령 실행
    • Redis CLI에서 SUBSCRIBE 명령을 사용하여 특정 이벤트를 구독할 수 있습니다:
SUBSCRIBE __keyevent@<DB번호>__:expired

 

Java 예시

  • config class로 설정
@Bean
public RedisMessageListenerContainer redisContainer(
        RedisConnectionFactory connectionFactory,
        ExpiredEventListener expiredEventListener,
        GenericEventListener genericEventListener) {
    RedisMessageListenerContainer container = new RedisMessageListenerContainer();
    container.setConnectionFactory(connectionFactory);

    // 만료 이벤트 리스너
    container.addMessageListener(expiredEventListener, new PatternTopic("__keyevent@<DB번호>__:expired"));

    // 일반 이벤트 리스너 추가 (SET, DEL 등)
    container.addMessageListener(genericEventListener, new PatternTopic("__keyevent@<DB번호>__:set"));
    container.addMessageListener(genericEventListener, new PatternTopic("__keyevent@<DB번호>__:del"));
    container.addMessageListener(genericEventListener, new PatternTopic("__keyevent@<DB번호>__:expire"));

    return container;
}

 

  • Listener class 생성
import org.springframework.data.redis.connection.Message;
import org.springframework.data.redis.connection.MessageListener;
import org.springframework.stereotype.Component;

@Component
public class GenericEventListener implements MessageListener {
    @Override
    public void onMessage(Message message, byte[] pattern) {
        String topic = new String(pattern); // 구독된 토픽
        String body = new String(message.getBody()); // 메시지 내용
        String channel = new String(message.getChannel()); // 메시지가 발생한 채널

        System.out.println("Topic: " + topic);
        System.out.println("Channel: " + channel);
        System.out.println("Message: " + body);

        // 추가적인 로직 작성
        if (topic.contains("set")) {
            System.out.println("A key was set.");
        } else if (topic.contains("del")) {
            System.out.println("A key was deleted.");
        } else if (topic.contains("expire")) {
            System.out.println("A key expiration was set.");
        }
    }
}

 

활용 예제

  1. 세션 관리
    • 사용자 세션이 만료되었을 때 알림을 받아 로그아웃 처리를 수행.
  2. 실시간 캐싱 시스템
    • 캐시된 데이터의 만료 시점에 새로운 데이터를 생성하거나 캐싱.
  3. 만료 기반 이벤트
    • 특정 키가 만료되었을 때 알림을 통해 후속 작업(예: 데이터 정리, 로그 기록)을 트리거.

 

주의사항

  1. 성능 이슈
    • 많은 키에 대해 만료 알림이 발생하면 Redis 성능에 영향을 줄 수 있습니다.
    • 이벤트 사용 시 성능 테스트를 권장합니다.
  2. 정확한 알림 보장 아님
    • 만료 알림은 이벤트로 전달되므로 네트워크 문제 등으로 인해 누락될 가능성이 있습니다.

 

내가 Redis를 사용했던 방법

  1. token(0)과 예약(1)으로 DB 번호를 Divide
  2. 1번 DB 데이터가 만료 시 이벤트 발생하도록 설정
  3. 만료시간을 토대로 rabbitMQ로 전달
  4. rabbitMQ에서 firebase로 데이터 전달
  5. 실패 시 dlx로 이동 후 값 오류가 아니면 다시 시도

'Project' 카테고리의 다른 글

JPA ) 더티체킹의 대한 궁금증 & 나의 사용방식  (1) 2024.12.22
Redis Setting에 대한 궁금증  (0) 2024.12.18