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.
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.
vivo Internet Technology
Sharing practical vivo Internet technology insights and salon events, plus the latest industry news and hot conferences.
How this landed with the community
Was this worth your time?
0 Comments
Thoughtful readers leave field notes, pushback, and hard-won operational detail here.