I’m an explorer by heart, so when I have to make a technical decision—like, say, choosing a Redis client—I go a-spelunking. Herein is the account of my exploration of the rhyming duo of Java clients: Jedis versus Lettuce.
Let’s start with the basics, and examine each client, to understand the differences between the two.
Lettuce is a Redis Java client that is fully non-blocking. It supports both synchronous and asynchronous communication. Its complex abstractions allow you to scale products easily.
Consider Lettuce as a more advanced client that supports Cluster, Sentinel, Pipelining, and codecs.
Jedis is a client library inside Redis that’s designed for performance and ease of use. Jedis is a lightweight offering compared to other Redis Java clients; it offers fewer features but can still handle large amounts of memory.
Due to its simpler functionality, Jedis is easier to use, but it only works with clusters synchronously. If you choose Jedis, you may find it less challenging to focus on the application and data rather than the data storage mechanism.
My plan was simple:
The gnomic goal of profit, like underpants, is always there. But the part that you can benefit from is the selection criteria. It will allow us to decide when Jedis is the right call and when Lettuce is the way to go. This is super important because we all know the answer to any question when selecting tools is, “it depends.”
Jedis is a client library inside Redis that’s designed for performance and ease of use. Jedis is a lightweight offering compared to other Redis Java clients; it offers fewer features but can still handle large amounts of memory.
Due to its simpler functionality, Jedis is easier to use, but it only works with clusters synchronously. If you choose Jedis, you may find it less challenging to focus on the application and data rather than the data storage mechanism.
My comparison plan was simple:
The gnomic goal of profit, like underpants, is always there. But the part that you can benefit from is the selection criteria. It allows us to decide when the Java client, Jedis, is the right call and when Lettuce software is the way to go. This is super important because we all know the answer to any tool selection question is, “It depends.”
To get to the bottom of the Jedis versus Lettuce debate, let’s compare code for the simplest of all exercises: setting and getting a value from a single instance of Redis.
First, we do this with Jedis:
Looking at the code, this is pretty simple. Create a connection. Use it. Close it.
Next, we do it with Lettuce:
This looks a bit more involved. There’s a Java client, a connection, and a command object. And their names and templated nature suggest that there might be multiple varieties of them. Maybe in addition to a StatefulRedisConnection<String, String> type, we have a stateless variety that takes a byte[]]? (Spoiler: there are multiple connection types for clustering and master/replica configurations, but not stateless ones.)
Once you’re beyond the setup and teardown, however, it’s the same basic code in either client: Create a connection. Use it. Close it.
Right now, for something as simple as this, Jedis looks easier. That makes sense since it has less code. But I am certain that the Lettuce software has all this stuff for a reason—probably to handle more advanced scenarios.
Jedis is entirely synchronous with the exception of pipelines. Pipelines allow Jedis asynchronous usage of Redis, but, unfortunately, they cannot be used alongside clustering. However, pipelines are easy enough to use:
Lettuce libraries support synchronous, asynchronous, and even reactive interfaces if you’re into that sort of thing (which I am). However, here’s an important note to make about the Lettuce library: These are all just layers of syntactic sugar on top of Lettuce’s multithreaded, event-based model that uses pipelining as a matter of course. Even when you use it synchronously, it’s asynchronous underneath.
We’ve seen the synchronous interface in action already with our super sophisticated set and get an example. But let’s take a look at the asynchronous example:
This sets and gets, just like the synchronous example, but clearly, this is more involved code. It’s also multi-threaded.
Jedis can handle multi-threaded applications just fine, but a Jedis connection is not thread-safe. So don’t share them. If you share a Jedis connection across threads, Redis blurts out all sorts of protocol errors, like:
expected '$' but got ' '
To solve these sorts of problems, use JedisPool—a thread-safe object that dispenses thread-unsafe Jedis objects. Using it is simple, like the rest of Jedis. Just ask for a thread and return it to the pool via .close() when you’re done. Here it is in action:
Each of these Jedis objects encapsulates a single connection to Redis, so (depending on how large your pool is) there may be blocking or idle connections. Furthermore, these connections are synchronous, so there’s always a degree of idleness.
I feel like I should talk about clustering, but there’s not much to say—at least in terms of comparisons. There’s plenty of capability to discuss, but both libraries support clustering. Unsurprisingly, Jedis is easier to use, but it works with clusters only synchronously. The Lettuce software is more difficult to use but is capable of synchronous, asynchronous, and reactive interaction with the cluster.
This is the recurring theme. And that shouldn’t be surprising. By its own admission, “Jedis was conceived to be EASY to use.” And Lettuce states, “Lettuce is a scalable Redis client for building non-blocking Reactive applications” right on its homepage.
Of course, if you’re using Redis Enterprise, you don’t have to worry about clustering as it’s handled server-side. Just use the non-clustered APIs of Jedis or Lettuce, manage your keys so they’re slotted to the correct shards, and you’re good to go.