Redis Pub/Sub

hoyong.eom·2024년 10월 20일
0

스프링

목록 보기
58/59
post-thumbnail

Redis

Pub/Sub 기능은 Kafka, RabbitMQ, Redis를 이용해서 구현할 수 있다.
그런데, 어떤 상황에서 kafka, RabbitMQ, Redis를 사용해야하는걸까?

이번 포스팅에서는 Redis를 이용한 Pub/Sub을 구현해보고, 잘 알려진 Redis Pub/Sub 문제를 알아보고자 한다.(토이 프로젝트에서 Pub/Sub을 사용해야하기 때문에 여러 가지를 구현해보려고 한다.)

Pub/Sub

Redis를 이용한 Pub/Sub에서 잘 알려진 문제는 이벤트 유실이다.
그렇다면 Redis를 이용한 Pub/Sub에서 이벤트 유실이 발생하는 이유가 무엇일까?

그 이유는 Publish에서 전달한 메시지(이벤트)가 메시지 큐에 저장되지 않고 바로 Subscribe에게 전송되기 때문에 처리할 Subscribe가 없다면 전달한 메시지는 유실이 될 수 있다.

그렇다면 Redis Pub/Sub를 사용해야하는 경우는 언제일까?

메시지가 실시간으로 빠르게 전달되어야 하는 경우, 메시지 유실을 감내할 수 있는 케이스

즉 정리하면 Redis Pub/Sub의 장/단점은 아래와 같다.

장점

  • 메시지가 큐에 저장되지 않음.
  • kafka의 컨슈머 그룹같은 분산처리 개념이 없음.
  • 메시지 발행시 push 방식으로 subscriber들에게 전송
  • subscriber가 늘어날수록 성능이 저하

단점

  • 실시간으로 빠르게 전송되어야 하는 메시지
  • 메시지 유실을 감내할 수 있는 케이스(메시지의 한시적으로만 유용한 케이스)
  • 최대 1회 전송(at-most-once)패턴이 적합한 경우
  • Subscriber들이 다양한 채널을 유동적으로 바꾸면서 한시적으로 구독하는 경우

Redis Pub/Sub 주요 코드 분석

@Configuration
@RequiredArgsConstructor
public class RedisConfig {

    private final RedisProperties redisProperties;


    @Bean
    public RedisConnectionFactory redisConnectionFactory() {
        return new LettuceConnectionFactory(redisProperties.getHost(), redisProperties.getPort());
    }

    @Bean
    public RedisTemplate<?, ?> redisTemplate() {
        RedisTemplate<?, ?> redisTemplate = new RedisTemplate<>();
        redisTemplate.setConnectionFactory(redisConnectionFactory());   //connection
        redisTemplate.setKeySerializer(new StringRedisSerializer());    // key
        redisTemplate.setValueSerializer(new Jackson2JsonRedisSerializer<>(String.class)); //Java Obj <-> JSON -> String Value
        return redisTemplate;
    }


    /**
     * Redis pub/sub 메시지 처리 Listener
     */
    @Bean
    public RedisMessageListenerContainer redisMessageListener() {
        RedisMessageListenerContainer container = new RedisMessageListenerContainer();
        container.setConnectionFactory(redisConnectionFactory());

        return container;
    }
}
  • RedisConnectionFactory : RedisMessageListenerContainer에서 Redis에 연결하기 위한 ConnectionFactory 객체
  • redisTemplate : Redis에 메세지를 전달하기 위한 Template
  • RedisMessageListenerContainer : 이벤트 관리 객체, 이 객체를 통해서 Publish한 이벤트에 해당하는 Listener가 호출된다.
redisMessageListenerContainer.addMessageListener(redisSubscribeLisnter, new ChannelTopic(channel));
  • addMessageListener : 이벤트를 처리할 리스너를 리스너 관리 객체인 RedisMessageListenerContainer에 보관
public void publish(ChannelTopic topic, MessageDto dto) {
        redisTemplate.convertAndSend(topic.getTopic(), dto);
    }
  • redisTemplate.converAndSend : 토픽(채널)로 메시지를 전달

참고

https://velog.io/@rainbowweb/Redis-%EC%97%B0%EC%8A%B5-2-pubsub-%EA%B5%AC%EC%84%B1
https://lucas-owner.tistory.com/68
https://oliveyoung.tech/blog/2023-08-07/async-process-of-coupon-issuance-using-redis/
https://velog.io/@gravitycage/Redis-PubSub-Performance
https://velog.io/@mooh2jj/PubSub-%EB%AA%A8%EB%8D%B8-Redis-vs-RabbitMQ

0개의 댓글