Spring에서 Redis 사용하기

How to use Redis in Spring

Posted by dydtjr1128 on April 03, 2019 · 7 mins read Redis

Redis

Redis는 In-memory 기반의 NoSQL DBMS로서 Key-Value의 구조를 가지고있다. 또한 속도가 빠르고 사용이 간편하다. 캐싱,세션관리,pub/sub 메시징 처리등에 사용된다.

Spring에서 Redis를 사용하기위한 라이브러리는 2가지가있다.

  • jedis
  • lettuce

jedis는 thread-safe하지 않기 때문에 jedis-pool을 사용해야한다. 그러나 비용이 증가하기 때문에 lettuce를 많이 사용한다.

 <dependency>
     <groupId>org.springframework.boot</groupId>
     <artifactId>spring-boot-starter-data-redis</artifactId>
 </dependency>
@Configuration
public class RedisConfiguration {
    
    @Bean
    public RedisConnectionFactory redisConnectionFactory() {
        LettuceConnectionFactory lettuceConnectionFactory = new LettuceConnectionFactory();
        return lettuceConnectionFactory;
    }
    @Bean
    public RedisTemplate<String, Object> redisTemplate() {
        RedisTemplate<String, Object> redisTemplate = new RedisTemplate<>();
        redisTemplate.setConnectionFactory(redisConnectionFactory());
        redisTemplate.setKeySerializer(new StringRedisSerializer());
        return redisTemplate;
    }
 
}

ettuceConnectionFactory.setHost("192.168.0.78") 및 ` .setPassword(“password”);`를 이용해 설정할 수 있으나 application.properties나 .yml 파일에 설정하는것을 권장한다.

 spring.redis.lettuce.pool.max-active=10
 spring.redis.lettuce.pool.max-idle=10
 spring.redis.lettuce.pool.min-idle=2
 spring.redis.port=6379
 spring.redis.host=127.0.0.1


Redis 사용 예제

GetSetService.java
@Service
public class GetSetService {
    
    @Autowired
    RedisTemplate<String, Object> redisTemplate;
    
    public void test() {
        //hashmap같은 key value 구조
        ValueOperations<String, Object> vop = redisTemplate.opsForValue();
        vop.set("jdkSerial", "jdk");
        String result = (String) vop.get("jdkSerial");
        System.out.println(result);//jdk
    }
}

위와 같은 경우 객체를 직렬화를 하여 바이트로 저장하기 때문에 출력시 이상한 문자열이 출력 될 수 있다. json등을 이용하여 해결 가능하다.

@Configuration
public class RedisConfiguration {

    @Bean
    public RedisConnectionFactory redisConnectionFactory() {
        LettuceConnectionFactory lettuceConnectionFactory = new LettuceConnectionFactory();
        return lettuceConnectionFactory;
    }

    @Bean
    public RedisTemplate<String, Object> redisTemplate() {
        RedisTemplate<String, Object> redisTemplate = new RedisTemplate<>();
        redisTemplate.setConnectionFactory(redisConnectionFactory());
        redisTemplate.setKeySerializer(new StringRedisSerializer());
        redisTemplate.setValueSerializer(new Jackson2JsonRedisSerializer<>(MyData.class));
        return redisTemplate;
    }

}

위와 같이 setValueSerializer() 메소드를 사용하여 직렬화 를 설정 할 수 있다.

여기서 Jackson이란?

Jackson은 text/html 형태의 문자가 아닌 객체등의 데이터를 JSON으로 처리해 주는 라이브러리 이다. Jackson 외에 Google에서 만든 GSONSimpleJSON 등이 있다. Spring 3.0 이후부터는 내부적으로 Jackson 관련 API 제공을 통하여 자동화 처리가 가능하도록 도와주었다.

Mydata.java
@Getter
@Setter
@ToString
@AllArgsConstructor
@NoArgsConstructor
public class MyData implements Serializable {
    private static final long serialVersionUID = -7353484588260422449L;
    private String studentId;
    private String name;
}
DataService.java
@Service
public class DataService {
    @Autowired
    RedisTemplate<String, Object> redisTemplate;

    public void test() {
        ValueOperations<String, Object> valueOperations = redisTemplate.opsForValue();
        MyData data = new MyData();
        data.setStudentId("1234566");
        data.setName("HongGilDong");
        valueOperations.set("key", data);

        MyData data2 = (MyData) valueOperations.get("key");
        System.out.println(data2);
    }
}


Redis Publish/Subscribe

RedisConfiguration.java
@Configuration
public class RedisConfiguration {

    @Bean
    public RedisConnectionFactory redisConnectionFactory() {
        LettuceConnectionFactory lettuceConnectionFactory = new LettuceConnectionFactory();
        return lettuceConnectionFactory;
    }

    @Bean
    public RedisTemplate<String, Object> redisTemplate() {
        RedisTemplate<String, Object> redisTemplate = new RedisTemplate<>();
        redisTemplate.setConnectionFactory(redisConnectionFactory());
        redisTemplate.setKeySerializer(new StringRedisSerializer());
        redisTemplate.setValueSerializer(new Jackson2JsonRedisSerializer<>(MyData.class));
        return redisTemplate;
    }

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

    @Bean
    RedisMessageListenerContainer redisContainer() {
        RedisMessageListenerContainer container = new RedisMessageListenerContainer();
        container.setConnectionFactory(redisConnectionFactory());
        container.addMessageListener(messageListenerAdapter(), topic());
        return container;
    }

    @Bean
    ChannelTopic topic() {
        return new ChannelTopic("Event");
    }
}
RedisService.java
@Service
public class RedisService implements MessageListener {
    public static List<String> messageList = new ArrayList<String>();

    @Override
    public void onMessage(Message message, byte[] pattern) {
        messageList.add(message.toString());
        System.out.println("Message received: " + message.toString());
    }
}

Subscribe를 하기 위해서는 서비스를 만들고, 토픽을 추가시켜주어야 한다.

References

https://woowabros.github.io/experience/2017/10/17/java-serialize2.html

https://jeong-pro.tistory.com/175