Jedis
GitHub Overview
redis/jedis
Redis Java client
Topics
Star History
Cache Library
Jedis
Overview
Jedis is the official Redis client library for Java, supporting high-performance connection pooling, Redis Cluster, Sentinel, RediSearch, RedisJSON, and all Redis features.
Details
Jedis is the official Redis client library for Java developed and maintained by Redis Labs. It provides simple and intuitive APIs while accessing all Redis features. It covers enterprise-level features including efficient connection management with JedisPool, distributed processing with Redis Cluster, high availability with Redis Sentinel, pipelining and transactions, Pub/Sub messaging, and Lua scripting support. The JedisPooled class simplifies the traditional try-with-resources pattern, enabling more concise Redis operations. It also supports Redis modules like RediSearch, RedisJSON, and RedisTimeSeries for advanced search, JSON operations, and time-series data processing. With easy integration through Maven and Gradle, comprehensive documentation, and active community support, it is widely adopted as the standard Redis client in the Java ecosystem.
Pros and Cons
Pros
- Official Support: Official development and maintenance by Redis Labs
- Rich Features: Complete support for all Redis features and modules (RediSearch, RedisJSON, etc.)
- High-Performance Connection Pooling: Efficient resource management with JedisPool
- Concise API: Intuitive and user-friendly Java API design
- Cluster Support: Automatic discovery and failover for Redis Cluster
- Enterprise Ready: Complete support for Sentinel, TLS, and authentication
- Active Community: Rich documentation and sample code
Cons
- Synchronous Focused: Limited support for asynchronous processing
- Connection Management Complexity: Need to optimize pool size and timeout settings
- Java Ecosystem Limited: Cannot be used outside Java/JVM languages
- Dependencies: Requires dependency libraries like Commons Pool and Apache HTTP Client
- Error Handling: Need to implement retry logic for connection errors
Official Links
- Jedis GitHub Repository
- Jedis Maven Central
- Redis Java Documentation
- Redis Official Documentation
- Jedis Wiki
Code Examples
Basic Setup and Maven Dependency
<!-- pom.xml -->
<dependency>
<groupId>redis.clients</groupId>
<artifactId>jedis</artifactId>
<version>5.1.0</version>
</dependency>
Simple Operations with JedisPooled
import redis.clients.jedis.JedisPooled;
public class RedisExample {
public static void main(String[] args) {
// Connection with JedisPooled (recommended method)
JedisPooled jedis = new JedisPooled("localhost", 6379);
// Basic operations
jedis.set("key", "value");
String value = jedis.get("key");
System.out.println(value); // "value"
// Set key with expiration
jedis.setex("tempkey", 60, "temporary value"); // Expires in 60 seconds
// List operations
jedis.lpush("mylist", "element1", "element2", "element3");
List<String> list = jedis.lrange("mylist", 0, -1);
System.out.println(list);
// Set operations
jedis.sadd("myset", "member1", "member2", "member3");
Set<String> members = jedis.smembers("myset");
System.out.println(members);
}
}
Connection Management with JedisPool
import redis.clients.jedis.JedisPool;
import redis.clients.jedis.JedisPoolConfig;
import redis.clients.jedis.Jedis;
public class JedisPoolExample {
private static JedisPool pool;
static {
// Pool configuration
JedisPoolConfig poolConfig = new JedisPoolConfig();
poolConfig.setMaxTotal(20); // Maximum connections
poolConfig.setMaxIdle(10); // Maximum idle connections
poolConfig.setMinIdle(2); // Minimum idle connections
poolConfig.setTestOnBorrow(true);
poolConfig.setTestOnReturn(true);
// Pool initialization
pool = new JedisPool(poolConfig, "localhost", 6379, 2000, "password");
}
public void performOperations() {
// Safe connection management with try-with-resources
try (Jedis jedis = pool.getResource()) {
jedis.set("pooled-key", "pooled-value");
String value = jedis.get("pooled-key");
System.out.println("Retrieved: " + value);
// Complex operations
jedis.hset("user:1", "name", "John Doe");
jedis.hset("user:1", "email", "[email protected]");
jedis.hset("user:1", "age", "30");
Map<String, String> user = jedis.hgetall("user:1");
System.out.println("User data: " + user);
}
}
public static void close() {
if (pool != null) {
pool.close();
}
}
}
Redis Cluster Operations
import redis.clients.jedis.JedisCluster;
import redis.clients.jedis.HostAndPort;
import java.util.HashSet;
import java.util.Set;
public class ClusterExample {
public static void main(String[] args) {
// Cluster nodes configuration
Set<HostAndPort> jedisClusterNodes = new HashSet<>();
jedisClusterNodes.add(new HostAndPort("127.0.0.1", 7379));
jedisClusterNodes.add(new HostAndPort("127.0.0.1", 7380));
jedisClusterNodes.add(new HostAndPort("127.0.0.1", 7381));
// Cluster connection
JedisCluster jedisCluster = new JedisCluster(jedisClusterNodes);
// Data operations in cluster
jedisCluster.set("cluster-key", "cluster-value");
String value = jedisCluster.get("cluster-key");
System.out.println("Cluster value: " + value);
// Place multiple keys in the same hash slot
jedisCluster.set("{user:1000}:profile", "user profile data");
jedisCluster.set("{user:1000}:preferences", "user preferences");
// Performance counters
jedisCluster.incr("page_views");
Long views = jedisCluster.get("page_views");
System.out.println("Page views: " + views);
jedisCluster.close();
}
}
Pipelining and Transactions
import redis.clients.jedis.Jedis;
import redis.clients.jedis.Pipeline;
import redis.clients.jedis.Transaction;
import redis.clients.jedis.Response;
public class AdvancedOperations {
public void demonstratePipelining() {
try (Jedis jedis = new Jedis("localhost", 6379)) {
// Execute multiple commands in batch with pipelining
Pipeline pipeline = jedis.pipelined();
Response<String> set1 = pipeline.set("pipe1", "value1");
Response<String> set2 = pipeline.set("pipe2", "value2");
Response<Long> incr = pipeline.incr("counter");
Response<List<String>> lrange = pipeline.lrange("mylist", 0, -1);
// Execute batch
pipeline.sync();
// Get results
System.out.println("Set result: " + set1.get());
System.out.println("Counter value: " + incr.get());
System.out.println("List contents: " + lrange.get());
}
}
public void demonstrateTransaction() {
try (Jedis jedis = new Jedis("localhost", 6379)) {
// Transaction with optimistic locking
String watchKey = "balance:1000";
jedis.watch(watchKey);
String balance = jedis.get(watchKey);
int currentBalance = Integer.parseInt(balance != null ? balance : "0");
if (currentBalance >= 100) {
Transaction tx = jedis.multi();
tx.decrBy(watchKey, 100);
tx.incrBy("balance:2000", 100);
List<Object> results = tx.exec();
if (results == null) {
System.out.println("Transaction failed due to concurrent modification");
} else {
System.out.println("Transaction successful: " + results);
}
} else {
jedis.unwatch();
System.out.println("Insufficient balance");
}
}
}
}
Pub/Sub Messaging
import redis.clients.jedis.Jedis;
import redis.clients.jedis.JedisPubSub;
public class PubSubExample {
// Custom message listener
static class MessageListener extends JedisPubSub {
@Override
public void onMessage(String channel, String message) {
System.out.println("Received message: " + message + " from channel: " + channel);
}
@Override
public void onSubscribe(String channel, int subscribedChannels) {
System.out.println("Subscribed to channel: " + channel);
}
@Override
public void onUnsubscribe(String channel, int subscribedChannels) {
System.out.println("Unsubscribed from channel: " + channel);
}
@Override
public void onPMessage(String pattern, String channel, String message) {
System.out.println("Pattern message: " + message + " from " + channel + " matching " + pattern);
}
}
public static void main(String[] args) {
// Publisher
Thread publisherThread = new Thread(() -> {
try (Jedis jedis = new Jedis("localhost", 6379)) {
for (int i = 0; i < 10; i++) {
jedis.publish("news", "Breaking news #" + i);
jedis.publish("weather", "Weather update #" + i);
Thread.sleep(1000);
}
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
}
});
// Subscriber
Thread subscriberThread = new Thread(() -> {
try (Jedis jedis = new Jedis("localhost", 6379)) {
MessageListener listener = new MessageListener();
jedis.subscribe(listener, "news", "weather");
}
});
subscriberThread.start();
publisherThread.start();
try {
publisherThread.join();
subscriberThread.interrupt();
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
}
}
}
Using RediSearch and RedisJSON
import redis.clients.jedis.JedisPooled;
import redis.clients.jedis.search.*;
import redis.clients.jedis.json.Path;
import com.google.gson.Gson;
public class ModulesExample {
static class Product {
public String name;
public String category;
public double price;
public String description;
public Product(String name, String category, double price, String description) {
this.name = name;
this.category = category;
this.price = price;
this.description = description;
}
}
public static void main(String[] args) {
JedisPooled jedis = new JedisPooled("localhost", 6379);
Gson gson = new Gson();
// RedisJSON operations
Product product = new Product("Laptop", "Electronics", 999.99, "High-performance laptop");
jedis.jsonSet("product:1", gson.toJson(product));
String productJson = jedis.jsonGet("product:1");
System.out.println("Stored product: " + productJson);
// RediSearch index creation
Schema schema = new Schema()
.addTextField("name", 5.0)
.addTextField("description", 1.0)
.addTagField("category")
.addNumericField("price");
IndexDefinition def = new IndexDefinition()
.setPrefixes(new String[]{"product:"});
try {
jedis.ftCreate("product-index", IndexOptions.defaultOptions().setDefinition(def), schema);
} catch (Exception e) {
// Index already exists
System.out.println("Index already exists");
}
// Execute search
Query query = new Query("laptop")
.addFilter(new Query.NumericFilter("price", 500, 1500))
.limit(0, 10);
SearchResult result = jedis.ftSearch("product-index", query);
System.out.println("Search results: " + result.getDocuments());
jedis.close();
}
}