Databases 15 min read

Lettuce vs Jedis: Features, Usage, and Comparison of Java Redis Clients

Lettuce, a thread‑safe, Netty‑based Java Redis client supporting synchronous, asynchronous, reactive, Cluster, Sentinel, pipelining and custom codecs, outperforms Jedis’s non‑thread‑safe pooled connections by reducing resource consumption, simplifying Spring integration, and offering advanced features like read‑write splitting, topology refresh, and optional pooling for high‑throughput applications.

vivo Internet Technology
vivo Internet Technology
vivo Internet Technology
Lettuce vs Jedis: Features, Usage, and Comparison of Java Redis Clients

During a technical discussion the author compares the three officially recommended Java Redis clients—Jedis, Lettuce, and Redisson—highlighting why Lettuce is gaining popularity.

What is Lettuce? Lettuce is described as an advanced, thread‑safe Redis client that supports synchronous, asynchronous, and reactive APIs, as well as Cluster, Sentinel, pipelining, and codecs.

Key Features

Advanced client with a simple API that abstracts implementation details.

Thread‑safe connection instances (based on Netty) allowing multiple threads to share a single connection, reducing the number of physical connections to the Redis server.

Supports sync, async, and reactive usage; even synchronous commands are executed over a non‑blocking I/O layer.

Full support for Redis Cluster, Sentinel, pipelining, and custom codecs.

Comparison with Jedis Jedis connections are not thread‑safe and require a connection pool, which can increase resource consumption. Lettuce’s thread‑safe design simplifies resource management and improves stability.

Usage in Spring Since Spring Data Redis 2.0, Lettuce is the default client (integrated since 1.6). Spring Session also uses Lettuce by default, indicating its maturity.

Quick Start Example

io.lettuce
lettuce-core
5.3.6.RELEASE
import io.lettuce.core.*;
// Syntax: redis://[password@]host[:port][/databaseNumber]
RedisClient redisClient = RedisClient.create("redis://password@localhost:6379/0");
StatefulRedisConnection
connection = redisClient.connect();
RedisCommands
syncCommands = connection.sync();
syncCommands.set("key", "Hello, Redis!");
connection.close();
redisClient.shutdown();

Cluster Support

RedisClusterClient redisClient = RedisClusterClient.create("redis://password@localhost:7379");

Sentinel Support

RedisClient redisClient = RedisClient.create("redis-sentinel://localhost:26379,localhost:26380/0#mymaster");

Pipelining in Cluster Lettuce does not expose a dedicated pipeline API for clusters, but pipelining can be achieved using async commands with manual flushing:

StatefulRedisConnection
connection = client.connect();
RedisAsyncCommands
commands = connection.async();
commands.setAutoFlushCommands(false);
List
> futures = new ArrayList<>();
for (int i = 0; i < iterations; i++) {
    futures.add(commands.set("key-" + i, "value-" + i));
    futures.add(commands.expire("key-" + i, 3600));
}
commands.flushCommands();
LettuceFutures.awaitAll(5, TimeUnit.SECONDS, futures.toArray(new RedisFuture[futures.size()]));
connection.close();

Batch Execution By defining a batch interface and using flush() after a configured batch size, commands can be sent in bulk without affecting other threads.

/**
 * Define batch commands
 */
@BatchSize(100)
public interface RedisBatchQuery extends Commands, BatchExecutor {
    RedisFuture
get(byte[] key);
    RedisFuture
> smembers(byte[] key);
    RedisFuture
> lrange(byte[] key, long start, long end);
    RedisFuture
> hgetall(byte[] key);
}
// Usage example
RedisClusterClient client = RedisClusterClient.create(DefaultClientResources.create(), "redis://" + address);
RedisCommandFactory factory = new RedisCommandFactory(connect, Arrays.asList(ByteArrayCodec.INSTANCE, ByteArrayCodec.INSTANCE));
RedisBatchQuery batchQuery = factory.getCommands(RedisBatchQuery.class);
for (RedisMetaGroup group : redisMetaGroups) {
    appendCommand(group, futures, batchQuery);
}
batchQuery.flush();

Read‑Write Splitting Lettuce allows configuring readFrom on a StatefulRedisClusterConnection to direct reads to replica nodes.

Automatic Topology Refresh Using ClusterClientOptions with topologyRefreshOptions enables the client to adapt to cluster changes such as scaling.

Connection Pooling Although Lettuce’s single connection is thread‑safe, a pool can be created via Apache Commons‑pool2 for high‑throughput scenarios:

RedisClusterClient clusterClient = RedisClusterClient.create(RedisURI.create(host, port));
GenericObjectPool
> pool =
    ConnectionPoolSupport.createGenericObjectPool(() -> clusterClient.connect(), new GenericObjectPoolConfig());
try (StatefulRedisClusterConnection
connection = pool.borrowObject()) {
    connection.sync().set("key", "value");
    connection.sync().blpop(10, "list");
}
pool.close();
clusterClient.shutdown();

Conclusion Lettuce offers a more convenient, high‑level API than Jedis, with thread‑safe connections that reduce resource usage and improve stability. It provides extensive configuration options for performance tuning and deep integration with Spring ecosystems, making it a strong choice for modern Java backend development.

JavaRedisConnection PoolJedisasyncLettuceSpring Data Redis
vivo Internet Technology
Written by

vivo Internet Technology

Sharing practical vivo Internet technology insights and salon events, plus the latest industry news and hot conferences.

0 followers
Reader feedback

How this landed with the community

login Sign in to like

Rate this article

Was this worth your time?

Sign in to rate
Discussion

0 Comments

Thoughtful readers leave field notes, pushback, and hard-won operational detail here.