Java com Redis
Java tem vários clientes Redis. Esta lição aborda o uso de Jedis e Lettuce.
Clientes Redis para Java
Clientes Redis Java mais utilizados:
- Jedis: leve, simples de usar, baseado em I/O bloqueante
- Lettuce: construído sobre Netty, suporta async, thread-safe
- Redisson: locks distribuídos, coleções distribuídas e outros recursos avançados
💡 Escolha: Use Jedis para cenários simples, Lettuce para cenários de alto desempenho, e Redisson para cenários distribuídos.
Jedis
Adicionando Dependências
Maven:
XML
<dependency>
<groupId>redis.clients</groupId>
<artifactId>jedis</artifactId>
<version>5.1.0</version>
</dependency>
Gradle:
GRADLE
implementation 'redis.clients:jedis:5.1.0'
Conexão Básica
JAVA
import redis.clients.jedis.Jedis;
public class RedisDemo {
public static void main(String[] args) {
// Conectar ao Redis
Jedis jedis = new Jedis("localhost", 6379);
// Testar conexão
System.out.println(jedis.ping()); // PONG
// Fechar conexão
jedis.close();
}
}
Conectando com Senha
JAVA
Jedis jedis = new Jedis("localhost", 6379);
jedis.auth("sua_senha");
Operações de String
JAVA
import redis.clients.jedis.Jedis;
Jedis jedis = new Jedis("localhost", 6379);
// SET e GET
jedis.set("nome", "Alice");
String nome = jedis.get("nome"); // "Alice"
// SET com expiração
jedis.setex("session", 3600, "dados"); // Expira após 1 hora
// MSET e MGET
jedis.mset("key1", "valor1", "key2", "valor2");
List<String> values = jedis.mget("key1", "key2");
// INCR
jedis.set("counter", "0");
Long count = jedis.incr("counter"); // 1
// DEL
jedis.del("nome");
Operações de Hash
JAVA
Jedis jedis = new Jedis("localhost", 6379);
// HSET e HGET
jedis.hset("user:1", "name", "Alice");
jedis.hset("user:1", "age", "25");
String name = jedis.hget("user:1", "name"); // "Alice"
// HMSET e HMGET
Map<String, String> user = new HashMap<>();
user.put("name", "Bob");
user.put("age", "30");
jedis.hset("user:2", user);
List<String> values = jedis.hmget("user:2", "name", "age");
// HGETALL
Map<String, String> allFields = jedis.hgetAll("user:2");
// HDEL
jedis.hdel("user:2", "age");
Operações de Lista
JAVA
Jedis jedis = new Jedis("localhost", 6379);
// LPUSH e RPUSH
jedis.lpush("mylist", "valor1", "valor2");
jedis.rpush("mylist", "valor3");
// LRANGE
List<String> list = jedis.lrange("mylist", 0, -1);
// LPOP e RPOP
String value = jedis.lpop("mylist");
String value2 = jedis.rpop("mylist");
// LLEN
long length = jedis.llen("mylist");
Operações de Conjunto
JAVA
Jedis jedis = new Jedis("localhost", 6379);
// SADD
jedis.sadd("myset", "a", "b", "c");
// SMEMBERS
Set<String> members = jedis.smembers("myset");
// SISMEMBER
boolean exists = jedis.sismember("myset", "a"); // true
// SREM
jedis.srem("myset", "a");
// SINTER, SUNION, SDIFF
jedis.sadd("set1", "a", "b", "c");
jedis.sadd("set2", "b", "c", "d");
Set<String> inter = jedis.sinter("set1", "set2"); // [b, c]
Operações de Conjunto Ordenado
JAVA
Jedis jedis = new Jedis("localhost", 6379);
// ZADD
Map<String, Double> scores = new HashMap<>();
scores.put("player1", 100.0);
scores.put("player2", 200.0);
jedis.zadd("leaderboard", scores);
// ZRANGE
Set<String> top = jedis.zrange("leaderboard", 0, 9);
// ZRANGE WITHSCORES
Set<Tuple> topWithScores = jedis.zrangeWithScores("leaderboard", 0, 9);
// ZSCORE
Double score = jedis.zscore("leaderboard", "player1");
// ZINCRBY
jedis.zincrby("leaderboard", 50.0, "player1");
Pool de Conexão Jedis
JAVA
import redis.clients.jedis.Jedis;
import redis.clients.jedis.JedisPool;
import redis.clients.jedis.JedisPoolConfig;
public class RedisPool {
private static JedisPool pool;
static {
JedisPoolConfig config = new JedisPoolConfig();
config.setMaxTotal(100); // Máximo de conexões
config.setMaxIdle(50); // Máximo de conexões ociosas
config.setMinIdle(10); // Mínimo de conexões ociosas
config.setTestOnBorrow(true); // Testar ao obter
pool = new JedisPool(config, "localhost", 6379);
}
public static Jedis getJedis() {
return pool.getResource();
}
public static void close() {
pool.close();
}
}
// Usando o pool de conexão
try (Jedis jedis = RedisPool.getJedis()) {
jedis.set("key", "valor");
String value = jedis.get("key");
}
Pipelining com Jedis
JAVA
Jedis jedis = new Jedis("localhost", 6379);
Pipeline pipeline = jedis.pipelined();
pipeline.set("key1", "value1");
pipeline.set("key2", "value2");
pipeline.set("key3", "value3");
pipeline.get("key1");
List<Object> results = pipeline.syncAndReturnAll();
Transações com Jedis
JAVA
Jedis jedis = new Jedis("localhost", 6379);
Transaction tx = jedis.multi();
tx.set("key1", "value1");
tx.set("key2", "value2");
tx.incr("counter");
List<Object> results = tx.exec();
Lettuce
Adicionando Dependências
Maven:
XML
<dependency>
<groupId>io.lettuce</groupId>
<artifactId>lettuce-core</artifactId>
<version>6.3.0</version>
</dependency>
Conexão Básica
JAVA
import io.lettuce.core.RedisClient;
import io.lettuce.core.RedisConnection;
import io.lettuce.core.api.StatefulRedisConnection;
import io.lettuce.core.api.sync.RedisCommands;
public class LettuceDemo {
public static void main(String[] args) {
// Criar cliente
RedisClient client = RedisClient.create("redis://localhost:6379");
// Criar conexão
StatefulRedisConnection<String, String> connection = client.connect();
// Obter comandos síncronos
RedisCommands<String, String> commands = connection.sync();
// Executar comandos
commands.set("key", "valor");
String value = commands.get("key");
// Fechar conexão
connection.close();
client.shutdown();
}
}
Operações Assíncronas
JAVA
import io.lettuce.core.RedisClient;
import io.lettuce.core.api.StatefulRedisConnection;
import io.lettuce.core.api.async.RedisAsyncCommands;
RedisClient client = RedisClient.create("redis://localhost:6379");
StatefulRedisConnection<String, String> connection = client.connect();
// Obter comandos assíncronos
RedisAsyncCommands<String, String> async = connection.async();
// SET assíncrono
RedisFuture<String> future = async.set("key", "valor");
// Aguardar resultado
String result = future.get();
Pool de Conexão Lettuce
JAVA
import io.lettuce.core.RedisClient;
import io.lettuce.core.resource.ClientResources;
import io.lettuce.core.resource.DefaultClientResources;
ClientResources resources = DefaultClientResources.builder()
.ioThreadPoolSize(4)
.computationThreadPoolSize(4)
.build();
RedisClient client = RedisClient.create(resources, "redis://localhost:6379");
Integração com Spring
Integração com Spring Boot
Adicionar dependência:
XML
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-redis</artifactId>
</dependency>
Configuração:
YAML
# application.yml
spring:
redis:
host: localhost
port: 6379
password: sua_senha
database: 0
lettuce:
pool:
max-active: 100
max-idle: 50
min-idle: 10
Uso:
JAVA
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
@Service
public class RedisService {
@Autowired
private RedisTemplate<String, Object> redisTemplate;
public void set(String key, Object value) {
redisTemplate.opsForValue().set(key, value);
}
public Object get(String key) {
return redisTemplate.opsForValue().get(key);
}
public void delete(String key) {
redisTemplate.delete(key);
}
}
Operações com RedisTemplate
JAVA
@Autowired
private RedisTemplate<String, Object> redisTemplate;
// Operações de string
redisTemplate.opsForValue().set("key", "valor");
Object value = redisTemplate.opsForValue().get("key");
// Operações de hash
redisTemplate.opsForHash().put("user:1", "name", "Alice");
Object name = redisTemplate.opsForHash().get("user:1", "name");
// Operações de lista
redisTemplate.opsForList().leftPush("mylist", "valor1");
Object value = redisTemplate.opsForList().leftPop("mylist");
// Operações de conjunto
redisTemplate.opsForSet().add("myset", "a", "b", "c");
Set<Object> members = redisTemplate.opsForSet().members("myset");
// Operações de conjunto ordenado
redisTemplate.opsForZSet().add("leaderboard", "player1", 100);
Set<Object> top = redisTemplate.opsForZSet().range("leaderboard", 0, 9);
Exemplos Práticos
Exemplo 1: Lock Distribuído (Jedis)
JAVA
import redis.clients.jedis.Jedis;
import java.util.UUID;
public class DistributedLock {
private Jedis jedis;
private String lockKey;
private String identifier;
private int expireTime;
public DistributedLock(Jedis jedis, String lockKey, int expireTime) {
this.jedis = jedis;
this.lockKey = lockKey;
this.expireTime = expireTime;
this.identifier = UUID.randomUUID().toString();
}
public boolean acquire() {
String result = jedis.set(lockKey, identifier, "NX", "EX", expireTime);
return "OK".equals(result);
}
public boolean release() {
String script =
"if redis.call('get', KEYS[1]) == ARGV[1] then " +
" return redis.call('del', KEYS[1]) " +
"else " +
" return 0 " +
"end";
Object result = jedis.eval(script, 1, lockKey, identifier);
return Long.valueOf(1).equals(result);
}
}
Exemplo 2: Utilitário de Cache
JAVA
import redis.clients.jedis.Jedis;
import redis.clients.jedis.JedisPool;
import com.fasterxml.jackson.databind.ObjectMapper;
public class RedisCache {
private JedisPool pool;
private ObjectMapper mapper = new ObjectMapper();
public RedisCache(JedisPool pool) {
this.pool = pool;
}
public void set(String key, Object value, int expireSeconds) {
try (Jedis jedis = pool.getResource()) {
String json = mapper.writeValueAsString(value);
jedis.setex(key, expireSeconds, json);
} catch (Exception e) {
e.printStackTrace();
}
}
public <T> T get(String key, Class<T> clazz) {
try (Jedis jedis = pool.getResource()) {
String json = jedis.get(key);
if (json != null) {
return mapper.readValue(json, clazz);
}
} catch (Exception e) {
e.printStackTrace();
}
return null;
}
}
❓ Perguntas Frequentes
P Como escolher entre Jedis e Lettuce?
R Jedis é simples mas não thread-safe. Lettuce é thread-safe e suporta async. Lettuce é recomendado.
P Por que Jedis precisa de um pool de conexão?
R Jedis não é thread-safe — cada thread precisa de sua própria conexão. Um pool de conexão reutiliza conexões para melhor desempenho.
P Qual cliente o Spring Boot usa por padrão?
R Spring Boot 2.x usa Lettuce por padrão.
P Como lidar com exceções de conexão Redis?
R Use try-with-resources para garantir que as conexões sejam fechadas e configure mecanismos de repetição.
P Como escolher entre RedisTemplate e Jedis?
R Use RedisTemplate para projetos Spring, Jedis ou Lettuce para projetos não Spring.
📖 Resumo
- Jedis: simples de usar, precisa de pool de conexão
- Lettuce: thread-safe, suporta async, construído sobre Netty
- Integração com Spring Boot: usa RedisTemplate
- Pools de conexão melhoram o desempenho reutilizando conexões
- Exemplos práticos: lock distribuído, utilitário de cache
📝 Atividades
- Operações básicas: Use Jedis para operações de string, hash e lista
- Pool de conexão: Configure um pool de conexão Jedis e teste a reutilização de conexão
- Integração Spring: Use RedisTemplate em um projeto Spring Boot
- Prático: Implemente um lock distribuído simples ou utilitário de cache
Próxima Lição
Na próxima lição, nós aprenderemos sobre Node.js com Redis, abordando operações Redis com Node.js.



