SERVER/Spring Boot

[Spring Boot] REDIS PUB/SUB ๊ตฌํ˜„

GaGah 2023. 1. 16. 00:17

๐Ÿ“ ๊ธฐ๋Šฅ ์ •์˜

message pub/sub ๊ธฐ๋Šฅ์œผ๋กœ ๋ˆ„๊ตฐ๊ฐ€ ๋ฉ”์„ธ์ง€๋ฅผ ๋ณด๋‚ด๊ฒŒ ๋˜๋ฉด ํŠน์ • ์ฑ„๋„์— ๊ตฌ๋…ํ•˜๊ณ  ์žˆ๋Š” ๋Œ€์ƒ์—๊ฒŒ ๋ฉ”์„ธ์ง€๊ฐ€ ์ „์†ก๋˜๋Š” ๊ตฌ์กฐ

 

redis pub/sub ๊ตฌ์กฐ

https://gh402.tistory.com/69

 

[REDIS] REDIS PUB/SUB ๊ตฌ์กฐ

โญ REDIS PUB/SUB ๊ธฐ๋Šฅ ์†Œ๊ฐœ Redis๋Š” ์บ์‹ฑ ์—ญํ•  ๋ฟ๋งŒ ์•„๋‹ˆ๋ผ message pub/sub ๊ธฐ๋Šฅ๋„ ๊ฐ€์ง€๊ณ  ์žˆ๋‹ค. ๊ฐ„๋‹จํ•œ ์ฑ„ํŒ…์„ ๊ตฌํ˜„ํ•˜๊ฑฐ๋‚˜, ํ•˜๋‚˜์˜ ํŠน์ • ๋ฉ”์„ธ์ง€๋ฅผ ์—ฌ๋Ÿฌ ์‚ฌ๋žŒ์ด ๋ฐ›์•„์•ผํ•  ๋•Œ ์‚ฌ์šฉํ•œ๋‹ค. ( ์•„๋ž˜์˜ ๊ทธ๋ฆผ ์ฐธ๊ณ 

gh402.tistory.com

 

๐Ÿญ ๋ ˆ๋””์Šค ์ž๋ฐ” ํด๋ผ์ด์–ธํŠธ

  • lettuce
  • Jedis
  • Redisson

spring boot 2.0 ์ด์ƒ ๋ถ€ํ„ฐ spring-boot-starter-data-redis ์— ๊ธฐ๋ณธ ํด๋ผ์ด์–ธํŠธ๋Š” lettuce ์ด๋‹ค. 

lettuce๋Š” Netty(๋น„๋™๊ธฐ ์ด๋ฒคํŠธ ๊ธฐ๋ฐ˜ ๊ณ ์„ฑ๋Šฅ ๋„คํŠธ์›Œํฌ ํ”„๋ ˆ์ž„์›Œํฌ) ๊ธฐ๋ฐ˜์˜ Redis ํด๋ผ์ด์–ธํŠธ์ด๋‹ค.

 

2.3.6.RELEASE ๋ฒ„์ „์— Lettuce client ๊ฐ€ ์‚ฌ์šฉ๋œ ๊ฒƒ์„ ํ™•์ธํ•  ์ˆ˜ ์žˆ๋‹ค.

๐Ÿญ  redis pub/sub ํŠน์ง•

Redis pub/sub์€ ๋ณด๋‚ด๋Š” ๋ฉ”์„ธ์ง€๋ฅผ ๋ณ„๋„๋กœ ์ €์žฅํ•˜์ง€ ์•Š๊ณ , ๋ฉ”์„ธ์ง€๋ฅผ ํ•œ ๋ฒˆ ๋ณด๋‚ด๋ฉด ์žฌ์ „์†ก์€ ์ผ์–ด๋‚˜์ง€ ์•Š๋Š”๋‹ค.

Redis ์–ด๋””์—๋„ ์ €์žฅ๋˜์ง€ ์•Š๊ณ , ํด๋ผ์ด์–ธํŠธ๊ฐ€ ๋ฉ”์„ธ์ง€ ๋ฐ›๋Š” ๊ฒƒ์„ ๋ณด์žฅํ•˜์ง€ ์•Š๋Š”๋‹ค.

์‹ค์‹œ๊ฐ„ ๋ฐ์ดํ„ฐ ์ฒ˜๋ฆฌํ•˜๋Š” ๋ฐ์— ๋งค์šฐ ์ ํ•ฉํ•˜์ง€๋งŒ ์œ„์˜ ๋‚ด์šฉ์„ ๋ฐ˜๋“œ์‹œ ์ธ์ง€ํ•˜๊ณ  ๊ฐœ๋ฐœ์„ ํ•ด์•ผํ•œ๋‹ค. 

 

 


๐Ÿ“ค Spring boot ๋กœ Redis pub/sub ๊ตฌํ˜„ 

1) redis config ์„ค์ •

spring-boot-starter-data-redis dependency ์ถ”๊ฐ€ํ•ด์ค˜์•ผ ํ•œ๋‹ค! (์ด ์ •๋„๋Š” ๋‹ค ์•Œ๊ฒ ์ง€๋งŒ,, ํ˜น์‹œ๋‚˜ ํ•˜์—ฌ!)
    @Bean
    public RedisMessageListenerContainer redisMessageListener(RedisConnectionFactory connectionFactory) {
        val container = new RedisMessageListenerContainer();
        container.setConnectionFactory(connectionFactory);
        return container;
    }

    @Bean
    public RedisTemplate<String, Object> redisTemplate(RedisConnectionFactory connectionFactory) {
        RedisTemplate<String, Object> redisTemplate = new RedisTemplate<>();
        redisTemplate.setConnectionFactory(connectionFactory);
        redisTemplate.setKeySerializer(new StringRedisSerializer());
        redisTemplate.setValueSerializer(new Jackson2JsonRedisSerializer<>(String.class));
        redisTemplate.setHashKeySerializer(new StringRedisSerializer());
        redisTemplate.setHashValueSerializer(new Jackson2JsonRedisSerializer<>(String.class));

        return redisTemplate;
    }

 

 

2) redis publish (๋ฉ”์„ธ์ง€ ๋ฐœ์†ก)

publish ํ•จ์ˆ˜๋ฅผ ํ†ตํ•ด ๋ฉ”์„ธ์ง€๋ฅผ ๋ฐœ์†กํ•˜๊ณ ์ž ํ•˜๋Š” topic ๊ณผ String ํ˜•ํƒœ์˜ ์ „๋‹ฌํ•  message๋ฅผ ํŒŒ๋ผ๋ฏธํ„ฐ๋กœ ๋„ฃ์–ด์ฃผ๋ฉด

topic์„ ๊ตฌ๋…ํ•˜๊ณ  ์žˆ๋Š” ๋ชจ๋“  client ์—๊ฒŒ ๋ฉ”์„ธ์ง€๊ฐ€ ์ „์†ก๋œ๋‹ค.

@Slf4j
@RequiredArgsConstructor
public class MessagePublish {
    private final RedisTemplate<String, Object> redisTemplate;
    
    public void publish(ChannelTopic topic, String message) {
        log.info("redis publish >> topic: {}, message: {}", topic.getTopic(), message);

        try {
            redisTemplate.convertAndSend(topic.getTopic(), message);
        } catch (Exception e) {
            log.error("redis connection error : {} ", e.getMessage());
        }
    }
}

 

3) redis publish (๋ฉ”์„ธ์ง€ ๋ฐœ์†ก)

3-1. @PostConstruct ์• ๋…ธํ…Œ์ด์…˜์„ ํ†ตํ•ด์„œ ์„œ๋ฒ„๊ฐ€ ์‹คํ–‰๋  ๋•Œ "channel"์ด๋ผ๋Š” ์ฑ„๋„์— ๋Œ€ํ•ด ๋ฉ”์„ธ์ง€๊ฐ€ ์˜ค๋Š”์ง€ ์ฐฝ๊ตฌ๋ฅผ ์—ด์–ด๋†“๋Š” ์—ญํ• ์„ ํ•œ๋‹ค.

 

3-2. MessageListener์˜ onMessageํ•จ์ˆ˜๋ฅผ ์˜ค๋ฒ„๋ผ์ด๋“œํ•ด์„œ Message๊ฐ€ ๋“ค์–ด์˜ค๋ฉด ํ•ด๋‹น ํ•จ์ˆ˜์—์„œ ๋ฉ”์„ธ์ง€๋ฅผ ์ฒ˜๋ฆฌํ•  ์ˆ˜ ์žˆ๋‹ค.  

@Slf4j
@Service
@RequiredArgsConstructor
public class MessageSub implements MessageListener {
    private final RedisTemplate<String, Object> redisTemplate;
    private final RedisMessageListenerContainer listenerContainer;

    private static final String REDIS_CHANNEL = "channel";

    @PostConstruct
    public void init() {
        listenerContainer.addMessageListener(this, new ChannelTopic(REDIS_CHANNEL));
    }

    @Override
    public void onMessage(Message message, byte[] pattern) {
        val now = System.currentTimeMillis();
        val msg = (String) redisTemplate.getValueSerializer().deserialize(message.getBody());
        
        log.info("redis recv message. message:{}, pattern:[{}], set now:{}", msg, new String(pattern), now);
    }
}

 

 

๐Ÿ“— ์ฐธ๊ณ ๋งํฌ

 

 

LIST