DB/Database

[Redis] Redis 라이브러리 3종 비교 (Spring redis vs Lettuce vs Redisson)

Nellie Kim 2024. 7. 28. 14:26
728x90

키밸류 저장소인 Redis는 유명한 클라이언트 라이브러리들이 3가지가 있습니다.

 

Lettuce, Redisson, Jedis가 있는데, 오늘은 스프링 데이터 레디스와 Lettuce, Redisson 이렇게 3가지를 비교하며 코드를 작성해보겠습니다.

 

(Jedis는 구현 방식이 간단하지만, 비동기 처리를 지원하지 않으며 Thread-safe 하지 않아 잘 쓰지 않는 추세라고 합니다.)

 

 

📝 목차

1. spring data redis

2. Lettuce

3. Redisson

사용 사례별 추천

 

 

💻 사용한 기술

  • spring boot : 3.3.1
  • java : 17
  • Maven
  • spring-data-redis : 3.3.1
  • lettuce : 6.3.1
  • redisson : 3.16.3

 

1. spring data redis

spring data redis 설정 코드

Spring Data Redis는 Redis와 상호작용하기 위한 고수준의 추상화를 제공합니다. Redis 클라이언트로 Lettuce를 사용하더라도 Spring Data Redis의 추상화된 API를 사용하여 보다 간단하게 Redis와 통신할 수 있습니다.

import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.data.redis.connection.RedisClusterConfiguration;
import org.springframework.data.redis.connection.RedisConnectionFactory;
import org.springframework.data.redis.connection.lettuce.LettuceConnectionFactory;
import org.springframework.data.redis.core.RedisTemplate;

import java.util.Arrays;

@Configuration
public class RedisConfiguration {
    @Value("${spring.redis.cluster.nodes}")
    private String clusterNodes;
    
    /**
     * RedisConnectionFactory 빈 생성
     * (LettuceConnectionFactory를 사용하여 Redis 서버와의 연결을 설정)
     *
     * @return RedisConnectionFactory 객체
     */
    @Bean
    public RedisConnectionFactory redisConnectionFactory() {
        RedisClusterConfiguration clusterConfig = new RedisClusterConfiguration(Arrays.asList(clusterNodes.split(", ")));
        clusterConfig.setMaxRedirects(maxRedirects);

        return new LettuceConnectionFactory(clusterConfig);
    }
 

    // **RedisTemplate**을 정의하여 RedisConnectionFactory를 주입합니다. 
    @Bean
    public RedisTemplate<String, Object> redisTemplate(RedisConnectionFactory redisConnectionFactory) {
        RedisTemplate<String, Object> redisTemplate = new RedisTemplate<>();
        redisTemplate.setConnectionFactory(redisConnectionFactory);
        return redisTemplate;
    }
}

 

spring data redis 사용 코드 (RedisTemplate 구현)

import lombok.RequiredArgsConstructor;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;

@RequiredArgsConstructor
@Service
public class RedisUtils {
    /**
     *  Redis 사용위한 util 클래스
     */
    private final RedisTemplate<String, Object> redisTemplate;

    /**
     * 지정된 키와 값으로 데이터를 Redis에 저장
     */
    public void setData(String key, String value) {
        redisTemplate.opsForValue().set(key, value);
    }

    /**
     * 지정된 키에 해당하는 데이터를 Redis에서 조회
     */
    public String getData(String key) {
        return (String) redisTemplate.opsForValue().get(key);
    }

    /**
     * 지정된 키에 해당하는 데이터를 Redis에서 삭제
     */
    public void deleteData(String key) {
        redisTemplate.delete(key);
    }
}

 

장점:

  • Spring 통합: Spring 애플리케이션에서 쉽게 통합할 수 있으며, Spring의 다양한 기능과 잘 통합됩니다.
  • 고수준 API: Redis에 대한 고수준 추상화를 제공하여 사용이 쉽습니다. (RedisTemplate을 통해 Redis와 상호작용)
  • 리포지토리 지원: Spring Data의 리포지토리 패턴을 사용하여 데이터 접근을 간편하게 할 수 있습니다.

 

단점:

  • 추가적인 레이어: Spring Data Redis는 추가적인 추상화 레이어를 제공하여 성능에 영향을 미칠 수 있습니다.
  • 유연성 부족: Lettuce나 Redisson에 비해 유연성이 떨어질 수 있습니다.

 

2. lettuce

lettuce 설정 코드

Lettuce는 Redis와의 저수준 통신을 가능하게 합니다. Lettuce를 직접 사용할 때는 RedisClusterClient, StatefulRedisClusterConnection, RedisClusterCommands 등을 명시적으로 설정하고 호출합니다.

import io.lettuce.core.RedisURI;
import io.lettuce.core.cluster.RedisClusterClient;
import io.lettuce.core.cluster.api.StatefulRedisClusterConnection;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

import java.util.Arrays;
import java.util.List;

/**
 * Lettuce 클러스터 설정을 위한 구성 클래스
 */
@Configuration
public class LettuceConfiguration {
    @Value("${spring.redis.cluster.nodes}")
    private String clusterNodes;
    

    /**
     * Redis 클러스터 클라이언트를 빈으로 등록합니다.
     * @param redisNodes Redis 클러스터 노드 URI 목록
     * @return RedisClusterClient 객체
     */
    @Bean
    public RedisClusterClient redisClusterClient(List<RedisURI> redisNodes) {
        // 주어진 Redis 클러스터 노드 URI를 사용하여 Redis 클러스터 클라이언트를 생성합니다.
        return RedisClusterClient.create(clusterNodes);
    }

    /**
     * Redis 클러스터 연결을 빈으로 등록합니다.
     * @param redisClusterClient Redis 클러스터 클라이언트
     * @return StatefulRedisClusterConnection 객체
     */
    @Bean
    public StatefulRedisClusterConnection<String, String> statefulRedisClusterConnection(RedisClusterClient redisClusterClient) {
        // Redis 클러스터 클라이언트를 사용하여 클러스터 연결을 생성합니다.
        return redisClusterClient.connect();
    }
}

 

lettuce 사용 코드 (StatefulRedisClusterConnection 구현)

import io.lettuce.core.cluster.api.StatefulRedisClusterConnection;
import io.lettuce.core.cluster.api.sync.RedisClusterCommands;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

/**
 * Redis 클러스터와 상호작용하는 서비스 클래스.
 * Lettuce 라이브러리를 사용하여 Redis 클러스터에 연결하고 명령을 실행합니다.
 */
@Service
public class LettuceService {

    // Redis 클러스터와의 상태를 유지하는 연결 객체
    @Autowired
    private StatefulRedisClusterConnection<String, String> connection;

    /**
     * Redis 클러스터에 명령을 실행하는 메서드.
     * 키-값 쌍을 설정하고, 해당 키에 대한 값을 조회합니다.
     */
    public void execute() {
        
        RedisClusterCommands<String, String> commands = connection.sync(); //🎯동기 방식으로 Redis 클러스터 명령을 실행할 수 있는 인터페이스를 가져옴

        // Redis에 "key"라는 키로 "value"를 저장합니다.
        commands.set("key", "value");

        // "key"에 대한 값을 Redis에서 조회합니다.
        String value = commands.get("key");

        // 조회한 값을 콘솔에 출력합니다.
        System.out.println(value);
    }
}

 

장점:

  • 비동기/동기 API 지원: Lettuce는 비동기, 동기 및 반응형 API를 모두 지원하여 다양한 요구에 맞게 사용할 수 있습니다.
  • 성능: 높은 성능과 낮은 지연 시간을 제공하며, Netty 기반의 비동기 네트워크 라이브러리를 사용합니다.
  • 클러스터 지원: Redis 클러스터와 고가용성 설정(마스터-슬레이브)을 지원합니다.
  • Thread-safe: 연결이 스레드에 안전하며, 다중 스레드 환경에서 사용할 수 있습니다.

 

단점:

  • 사용자 경험: 다른 라이브러리보다 사용이 더 복잡할 수 있으며, 추가적인 설정이 필요합니다. (RedisClusterClient, StatefulRedisClusterConnection, RedisClusterCommands 등을 직접 설정하고 사용)
  • 추상화 레벨: Spring Data Redis에 비해 추상화 레벨이 낮아 사용 시 더 많은 작업이 필요할 수 있습니다.

 

3. Redisson

redisson 설정 코드

package com.redis.common;

import org.redisson.Redisson;
import org.redisson.api.RedissonClient;
import org.redisson.config.Config;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

import java.util.Arrays;

/**
 *  Redis 설정 클래스
 */
@Configuration
public class RedissonConfig {
    @Value("${spring.redis.cluster.nodes}")
    private String clusterNodes;

    @Bean
    public RedissonClient redissonClient() {
        Config config = new Config();
        config.useClusterServers()
                .addNodeAddress(clusterNodes.split(","));
        return Redisson.create(config);
    }
}

Redisson은 자체적으로 Redis 서버와의 연결을 관리하며, 설정이 간편하고 직관적입니다. spring-data-redis 처럼 RedisConnectionFactory 같은 연결 로직을 작성하지 않아도 됩니다.

redisson 사용 코드 (RedissonClient 구현)

package com.redis.common;

import lombok.RequiredArgsConstructor;
import org.redisson.api.RBucket;
import org.redisson.api.RedissonClient;

/**
 * RedissonClient를 사용하여 Redis와 상호작용하는 기능을 제공합니다.
 */
@RequiredArgsConstructor
public class RedissonClientService {
    private final RedissonClient redissonClient;  // Redisson 클라이언트 객체

    /**
     * 주어진 키에 해당하는 데이터를 Redis에서 조회합니다.
     */
    public ActionData get(String key) {
        RBucket<ActionData> bucket = redissonClient.getBucket(key);  // 키에 해당하는 Redis 버킷을 가져옴
        return bucket.get();  // 버킷에서 데이터 조회
    }

    /**
     * 주어진 키와 값으로 데이터를 Redis에 저장합니다.
     */
    public void set(String key, ActionData value) {
        RBucket<ActionData> bucket = redissonClient.getBucket(key);  // 키에 해당하는 Redis 버킷을 가져옴
        bucket.set(value);  // 버킷에 데이터 저장
    }
}

 

장점:

  • 풍부한 기능: 분산 객체, 서비스 및 Redis 기반의 데이터 구조를 지원하여 사용자가 쉽게 사용할 수 있습니다. 예를 들어, 분산 락, 분산 컬렉션, 분산 캐시 등을 제공합니다.
  • RBucket 등 고수준 추상화: RBucket, RMap, RList 등의 고수준 API를 제공하여 개발자가 쉽게 사용할 수 있습니다.
  • 성능 및 안정성: 고성능을 제공하며, 네트워크 및 Redis 서버 장애를 처리하는 다양한 기능을 제공합니다.
  • 편리한 설정: 사용이 간편하며, 설정이 직관적입니다.

 

단점:

  • 추가 의존성: 다른 Redis 클라이언트에 비해 기능이 많아 의존성 크기가 클 수 있습니다.
  • 일부 기능의 복잡성: 모든 기능을 사용하지 않으면 오버헤드가 될 수 있습니다.

 

사용 사례별 추천

  1. 단순한 고성능 Redis 클라이언트 필요 시: Lettuce
  2. Spring 애플리케이션과의 통합 및 리포지토리 패턴 활용 시: Spring Data Redis
  3. 분산 데이터 구조 및 고수준 추상화가 필요한 경우: Redisson

각 라이브러리는 고유한 장점과 단점을 가지고 있으며, 프로젝트의 요구 사항에 따라 적절한 것을 선택하면 됩니다.

 

Redis와의 통합이 주요 요구 사항이라면 Spring Data Redis가 좋을 수 있으며, 비동기 처리가 중요하다면 Lettuce가 적합할 수 있습니다. 풍부한 기능과 고수준 추상화가 필요하다면 Redisson이 좋은 선택이라고 합니다.