← Volver al listado de tecnologías
Clientes de Valkey
Clientes
Python
Instalación
pip install valkey
# o para compatibilidad
pip install redis
Conexión básica
import valkey
# Conexión simple
r = valkey.Valkey(host='localhost', port=6379, db=0)
# Con URL
r = valkey.from_url('valkey://localhost:6379/0')
# Con opciones
r = valkey.Valkey(
host='localhost',
port=6379,
password='password',
decode_responses=True, # Retorna strings en lugar de bytes
socket_timeout=5,
socket_connect_timeout=5
)
Operaciones comunes
# Strings
r.set('nombre', 'Juan')
r.get('nombre')
r.setex('sesion', 3600, 'datos') # Con TTL
# Hashes
r.hset('usuario:1', mapping={'nombre': 'Ana', 'edad': 25})
r.hget('usuario:1', 'nombre')
r.hgetall('usuario:1')
# Listas
r.lpush('tareas', 'tarea1', 'tarea2')
r.rpop('tareas')
r.lrange('tareas', 0, -1)
# Sets
r.sadd('tags', 'python', 'valkey')
r.smembers('tags')
# Sorted Sets
r.zadd('ranking', {'player1': 100, 'player2': 200})
r.zrange('ranking', 0, -1, withscores=True)
Async con asyncio
import asyncio
import valkey.asyncio as valkey
async def main():
r = valkey.from_url('valkey://localhost')
await r.set('clave', 'valor')
valor = await r.get('clave')
await r.close()
asyncio.run(main())
Pub/Sub
# Publicador
r.publish('canal', 'mensaje')
# Suscriptor
pubsub = r.pubsub()
pubsub.subscribe('canal')
for mensaje in pubsub.listen():
if mensaje['type'] == 'message':
print(mensaje['data'])
Node.js
Instalación
npm install redis
# o específico de valkey
npm install @valkey/valkey-js
Conexión
import { createClient } from 'redis';
const client = createClient({
url: 'redis://localhost:6379'
});
client.on('error', err => console.log('Error:', err));
await client.connect();
Operaciones
// Strings
await client.set('nombre', 'Juan');
const nombre = await client.get('nombre');
await client.setEx('sesion', 3600, 'datos');
// Hashes
await client.hSet('usuario:1', { nombre: 'Ana', edad: '25' });
const user = await client.hGetAll('usuario:1');
// Listas
await client.lPush('tareas', ['tarea1', 'tarea2']);
const tarea = await client.rPop('tareas');
// Sets
await client.sAdd('tags', ['node', 'valkey']);
const tags = await client.sMembers('tags');
// Sorted Sets
await client.zAdd('ranking', [
{ score: 100, value: 'player1' },
{ score: 200, value: 'player2' }
]);
const ranking = await client.zRange('ranking', 0, -1);
Pub/Sub
// Suscriptor
const subscriber = client.duplicate();
await subscriber.connect();
await subscriber.subscribe('canal', (mensaje) => {
console.log('Recibido:', mensaje);
});
// Publicador
await client.publish('canal', 'mensaje');
Go
Instalación
go get github.com/valkey-io/valkey-go
# o compatible redis
go get github.com/redis/go-redis/v9
Conexión
package main
import (
"context"
"github.com/redis/go-redis/v9"
)
func main() {
ctx := context.Background()
rdb := redis.NewClient(&redis.Options{
Addr: "localhost:6379",
Password: "",
DB: 0,
})
defer rdb.Close()
}
Operaciones
// Strings
err := rdb.Set(ctx, "nombre", "Juan", 0).Err()
nombre, err := rdb.Get(ctx, "nombre").Result()
// Con TTL
err = rdb.SetEx(ctx, "sesion", "datos", time.Hour).Err()
// Hashes
err = rdb.HSet(ctx, "usuario:1", map[string]interface{}{
"nombre": "Ana",
"edad": 25,
}).Err()
user, err := rdb.HGetAll(ctx, "usuario:1").Result()
// Listas
err = rdb.LPush(ctx, "tareas", "tarea1", "tarea2").Err()
tarea, err := rdb.RPop(ctx, "tareas").Result()
// Sets
err = rdb.SAdd(ctx, "tags", "go", "valkey").Err()
tags, err := rdb.SMembers(ctx, "tags").Result()
Pub/Sub
// Suscriptor
pubsub := rdb.Subscribe(ctx, "canal")
ch := pubsub.Channel()
go func() {
for msg := range ch {
fmt.Println(msg.Channel, msg.Payload)
}
}()
// Publicador
rdb.Publish(ctx, "canal", "mensaje")
Java
Maven
<dependency>
<groupId>redis.clients</groupId>
<artifactId>jedis</artifactId>
<version>5.0.0</version>
</dependency>
Uso básico
import redis.clients.jedis.Jedis;
import redis.clients.jedis.JedisPool;
// Con pool
JedisPool pool = new JedisPool("localhost", 6379);
try (Jedis jedis = pool.getResource()) {
jedis.set("nombre", "Juan");
String nombre = jedis.get("nombre");
jedis.hset("usuario:1", "nombre", "Ana");
Map<String, String> user = jedis.hgetAll("usuario:1");
}
Rust
Cargo.toml
[dependencies]
redis = "0.24"
tokio = { version = "1", features = ["full"] }
Uso
use redis::Commands;
fn main() -> redis::RedisResult<()> {
let client = redis::Client::open("redis://127.0.0.1/")?;
let mut con = client.get_connection()?;
let _: () = con.set("nombre", "Juan")?;
let nombre: String = con.get("nombre")?;
Ok(())
}
Patrones comunes
Wrapper con reintentos
import time
from functools import wraps
def retry(max_attempts=3, delay=1):
def decorator(func):
@wraps(func)
def wrapper(*args, **kwargs):
for attempt in range(max_attempts):
try:
return func(*args, **kwargs)
except valkey.ConnectionError:
if attempt < max_attempts - 1:
time.sleep(delay)
else:
raise
return wrapper
return decorator
@retry(max_attempts=3)
def get_data(key):
return r.get(key)
Cache decorator
def cache(ttl=300):
def decorator(func):
@wraps(func)
def wrapper(*args, **kwargs):
key = f"{func.__name__}:{args}:{kwargs}"
cached = r.get(key)
if cached:
return json.loads(cached)
result = func(*args, **kwargs)
r.setex(key, ttl, json.dumps(result))
return result
return wrapper
return decorator
@cache(ttl=60)
def get_user(user_id):
# Consulta costosa a DB
return db.get_user(user_id)
Repository pattern
class UserRepository:
def __init__(self, valkey_client):
self.r = valkey_client
def get(self, user_id):
data = self.r.hgetall(f'user:{user_id}')
return data if data else None
def save(self, user_id, data):
self.r.hset(f'user:{user_id}', mapping=data)
def delete(self, user_id):
self.r.delete(f'user:{user_id}')
Comparativa de clientes
| Lenguaje | Cliente | Async | Cluster | Sentinel |
|---|---|---|---|---|
| Python | valkey-py | ✓ | ✓ | ✓ |
| Node.js | redis | ✓ | ✓ | ✓ |
| Go | go-redis | ✓ | ✓ | ✓ |
| Java | Jedis | ✓ | ✓ | ✓ |
| Rust | redis-rs | ✓ | ✓ | ✓ |
Ejercicios
- Implementa un cache con TTL en tu lenguaje favorito
- Crea un sistema pub/sub entre dos servicios
- Implementa el patrón repository para una entidad
Resumen
- Todos los lenguajes tienen clientes maduros
- Usar pools de conexiones en producción
- Implementar reintentos para resiliencia
- Patrones: cache decorator, repository, pub/sub