과거 Jedis를 사용하고 있는 제게 주변에서 'Lettuce 안써요?', '시간 날 때 Lettuce로 전환하자'라는 이야기를 듣고 도대체 Lettuce가 뭔데? 라는 생각이 들었습니다.
다른 관심사에 밀려 원래 있던 의문이 희미해져 갈때쯤 회사 업무로 redis를 활용할 기회가 생겨 redis에 대한 공부를 시작하게 되었습니다. 이번 글은 대표적인 Redis Java Client 3가지에 대해 분석해보고 비교하는 시간을 가져볼 것이며 redis에 기본 개념을 알고 싶은 분들은 Redis에 대해 알아보자
을 읽어주시면 감사하겠습니다.
Jedis github에서 소개하는 Jedis는 다음과 같습니다.
Jedis is a Java client for Redis designed for performance and ease of use.
using-jedis-in-a-multithreaded-environment을 참고할 경우 다음과 같은 주의사항이 안내되어 있습니다.
You shouldn't use the same instance from different threads because you'll have strange errors. And sometimes creating lots of Jedis instances is not good enough because it means lots of sockets and connections, which leads to strange errors as well. A single Jedis instance is not threadsafe! To avoid these problems, you should use JedisPool, which is a threadsafe pool of network connections. You can use the pool to reliably create several Jedis instances, given you return the Jedis instance to the pool when done. This way you can overcome those strange errors and achieve great performance.
멀티스레드 환경일 경우 jedis 사용시 각 스레드에서 아래와 같이 인스턴스를 생성하여 사용하는 것을 권장합니다.
JedisPool pool = new JedisPool(new JedisPoolConfig(), "localhost");
Lettuce github에서 소개하는 Lettuce는 다음과 같습니다.
Lettuce is a scalable thread-safe Redis client for synchronous, asynchronous and reactive usage. Multiple threads may share one connection if they avoid blocking and transactional operations such as BLPOP and MULTI/EXEC. Lettuce is built with netty. Supports advanced Redis features such as Sentinel, Cluster, Pipelining, Auto-Reconnect and Redis data models.
jedis vs lettuce을 읽어보시면 코드 구현의 차이도 발생하는 것을 볼 수 있습니다.
package com.guyroyse.blogs.lettucevsjedis;
import redis.clients.jedis.Jedis;
public class JedisSetGet {
private static final String YOUR_CONNECTION_STRING = "redis://:foobared@yourserver:6379/0";
public static void main(String[] args) {
Jedis jedis = new Jedis(YOUR_CONNECTION_STRING);
jedis.set("foo", "bar");
String result = jedis.get("foo");
jedis.close();
System.out.println(result); // "bar"
}
}
package com.guyroyse.blogs.lettucevsjedis;
import io.lettuce.core.RedisClient;
import io.lettuce.core.api.StatefulRedisConnection;
import io.lettuce.core.api.sync.RedisCommands;
public class LettuceSetGet {
private static final String YOUR_CONNECTION_STRING = "redis://:foobared@yourserver:6379/0";
public static void main(String[] args) {
RedisClient redisClient = RedisClient.create(YOUR_CONNECTION_STRING);
StatefulRedisConnection<String, String> connection = redisClient.connect();
RedisCommands<String, String> sync = connection.sync();
sync.set("foo", "bar");
String result = sync.get("foo");
connection.close();
redisClient.shutdown();
System.out.println(result); // "bar"
}
}
Redission github에서 소개하는 Lettuce는 다음과 같습니다.
High-performance async and lock-free Java client for Redis and Valkey based on Netty framework.
redis는 서로 다른 프로세스가 공유 리소스를 상호 배타적인 방식으로 사용하기 위해서 분산 잠금 패턴을 활용해야 한다는 글을 공유합니다.
이 중 대표적인 분산 잠금 패턴을 구현한 라이브러리로 Redisson을 소개하고 있습니다.
Lettuce Replacement:
Why Redisson is the Best Lettuce Alternative 인용시 lettuce보다 더 좋은 점은 다음과 같습니다.
주요 기능을 표로 작성하면 다음과 같은 차이를 알 수 있습니다.
| 특징 | Jedis | Lettuce | Redisson |
|---|---|---|---|
| API 스타일 | 동기식 | 동기식 + 비동기식 + 리액티브 | 동기식 + 비동기식 + 리액티브 |
| 멀티스레드 지원 | 불안전 | 안전 (싱글 연결 공유) | 안전 (싱글 연결 공유) |
| 주요 사용 사례 | 단순한 Redis 작업 | 고성능, 비동기/리액티브 시스템 | 분산 락, 분산 데이터 구조 |
| 성능 | 빠름 | 매우 빠름 | 비교적 느림 |
| 기능 지원 | 기본 Redis 기능 | 모든 Redis 기능 | 모든 Redis 기능 + 고수준의 분산 기능 |
| 초기 학습 곡선 | 낮음 | 중간 | 중간~높음 |
| 종속성 크기 | 작음 | 중간 | 큼 |
일반적인 상황에선 그냥 Jedis를 사용한다.
멀티스레스 환경 또는 분산 시스템일 경우 Redisson을 사용하는게 일반적으로 좋은 선택이다.
Lettuce는 성능면에서 Redission이 문제가 있을 경우 도입 검토를 진행한다. (다만 분산 락은 구현해야 한다.)