Hello

[Spring Boot] Redis Pub/Sub 사용 본문

spring

[Spring Boot] Redis Pub/Sub 사용

nari0_0 2023. 11. 9. 19:41
728x90

 

예전에 redis pub기능을 사용했는데 오늘 pub / sub 사용하는 방법을 간단히 정리하려고 한다.

Redis Publish/Subscribe

- 특정 subscribe에게 메시지를 보내는 개념이 아니며 구독자 있는지, 없는지, 누구인지 알지 못한 채 채널로 메시지를 publish 합니다. 

- 푸시된 메시지를 따로 보관하지 않는다.

- 구독자가 메세지를 받는 것을 보장하지 않아, subscribe 대상이 없는 상황에서 메시지를 publish하면 메시지는 publish 되고 보낼 곳이 없어 버려진다. 전송 보장을 하지 않는다.

spring-boot-starter-data-redis dependency를 사용해 redis pub/sub 하는 방법

RedisAutoConfigration 에서 자동으로 RedisTemplate StringRedisTemplate 빈 등록 해준다. 때문에 프로퍼티 설정만 해주어도 다른 config 설정없이 redis 사용이 가능하다.

sping boot2 redis는 기본적으로 lettuce를 사용합니다.

publish

message 보내는 방법은 간단합니다. redisTemplate.convertAndSend(topic, message)를 사용해 메시지 전송 합니다.

MessagePublisher 인터페이스를 제공하지 않습니다.

@Slf4j
@Service
public class RedisPublisherService {
    @Autowired
    private StringRedisTemplate stringRedisTemplate;
    @Value("${channel.name}")
    private String channelName;

    public void pubMessage(String message) {
        log.info(message);
        stringRedisTemplate.convertAndSend(channelName, message);
    }
}

Subscriber

Spring Data Redis가 제공하는 MessageListener 인터페이스를 구현합니다.

@Slf4j
public class RedisListenerService implements MessageListener {
    @Override
    public void onMessage(Message message, byte[] pattern) {
        log.info("message =>{}", message);
        log.info("channel =>{}", new String(pattern));
    }
}

구현한 MessageListener는 실제 수신을 위해 adapter, listener container에 등록해야합니다.

  • MessageListenerAdapter
    • 컨테이너에 등록된 토픽에 메시지가 온 경우 메시지를 받아 처리 하는 클래스
  • MessageListenerContainer
    • 메시지 리스너에 대한 비동기 동작 제공
    • 서버 구동 시 등록된 모든 주제를 구독하기 위해 컨테이너 이전에 리스너를 등록
    • 채널의 메시지를 받는데 사용
    • MessageListener를 등록하는데 사용
@Configuration
public class RedisConfig{
    @Bean
    public MessageListenerAdapter messageListenerAdapter() {
        return new MessageListenerAdapter(new RedisListenerService());
    }
    @Bean
    public RedisMessageListenerContainer redisContainer(RedisConnectionFactory redisConnectionFactory,
                                                        ChannelTopic topic) {
        RedisMessageListenerContainer container
                = new RedisMessageListenerContainer();
        container.setConnectionFactory(redisConnectionFactory);
        container.addMessageListener(messageListenerAdapter(), topic);
        return container;
    }

    @Value("${channel.name}")
    private String channelName;
    
    @Bean
    public ChannelTopic topic(){
        return new ChannelTopic(channelName);
    }
}

 

 

참고 : https://medium.com/frientrip/pub-sub-%EC%9E%98-%EC%95%8C%EA%B3%A0-%EC%93%B0%EC%9E%90-de9dc1b9f739

https://inpa.tistory.com/entry/REDIS-%F0%9F%93%9A-PUBSUB-%EA%B8%B0%EB%8A%A5-%EC%86%8C%EA%B0%9C-%EC%B1%84%ED%8C%85-%EA%B5%AC%EB%8F%85-%EC%95%8C%EB%A6%BC

https://jojoldu.tistory.com/418

https://www.geeksforgeeks.org/redis-publish-subscribe/

https://www.baeldung.com/spring-data-redis-properties

728x90