Developer Tools

Redis más allá del caché: Estructuras de datos, Pub/Sub y aplicaciones en tiempo real

Aprende a usar Redis como algo más que un caché: explora sus estructuras de datos, mensajería pub/sub, streams y patrones para construir aplicaciones rápidas y escalables.

10 min de lectura

Sala de servidores con conexiones luminosas

La mayoría de los desarrolladores conocen Redis como "ese caché rápido". Pero Redis es un servidor de estructuras de datos en memoria con todas las funciones posibles, capaz de gestionar sesiones, clasificaciones en tiempo real, limitación de velocidad, colas de mensajes y mucho más — todo con una latencia inferior al milisegundo.

Por qué Redis es tan rápido

Redis almacena todo en memoria y usa un bucle de eventos de un solo hilo para procesar comandos. Sin I/O de disco en lecturas, sin contención de bloqueos, sin cambios de contexto. El resultado: más de 100.000 operaciones por segundo en hardware modesto.

Comparación típica de latencia:
┌─────────────────┬──────────────┐
│ Operación       │ Latencia     │
├─────────────────┼──────────────┤
│ Redis GET       │ 0.1 ms       │
│ PostgreSQL SEL  │ 1-5 ms       │
│ REST API call   │ 50-200 ms    │
│ Disk read       │ 5-10 ms      │
└─────────────────┴──────────────┘

Estructuras de datos principales

Redis no es solo clave-valor. Soporta ricas estructuras de datos que se corresponden directamente con necesidades habituales de las aplicaciones.

Strings — el bloque fundamental

Los strings almacenan texto, números o datos binarios de hasta 512 MB:

SET user:1001:name "Alice"
GET user:1001:name          # "Alice"

# Contador atómico
INCR page:views             # 1, 2, 3, ...
INCRBY cart:total 2500      # Añadir 25.00 (almacenar en céntimos)

# Claves con expiración (TTL)
SET session:abc123 "{...}" EX 3600   # Expira en 1 hora
TTL session:abc123                    # Segundos restantes

Hashes — objetos ligeros

Los hashes son perfectos para almacenar objetos sin la sobrecarga de la serialización:

HSET user:1001 name "Alice" email "alice@example.com" plan "pro"
HGET user:1001 name         # "Alice"
HGETALL user:1001           # Todos los campos y valores
HINCRBY user:1001 logins 1  # Incremento atómico de campo

Los hashes usan 10 veces menos memoria que almacenar cada campo como una clave independiente.

Lists — colas y feeds

Colecciones ordenadas que admiten push/pop desde ambos extremos:

LPUSH notifications:alice "Nuevo comentario en tu publicación"
LPUSH notifications:alice "Tienes un nuevo seguidor"
LRANGE notifications:alice 0 9    # Últimas 10 notificaciones

# Usar como cola (productor/consumidor)
RPUSH queue:emails "send-welcome"
LPOP queue:emails                  # Procesar siguiente trabajo

Sets — colecciones únicas

Colecciones desordenadas de strings únicos:

SADD tags:post:42 "redis" "database" "nosql"
SMEMBERS tags:post:42             # Todas las etiquetas
SISMEMBER tags:post:42 "redis"    # true

# Operaciones con sets
SINTER tags:post:42 tags:post:99  # Etiquetas en común
SUNION tags:post:42 tags:post:99  # Todas las etiquetas combinadas

Sorted Sets — clasificaciones y rankings

Sets con una puntuación para cada miembro, ordenados automáticamente:

ZADD leaderboard 1500 "alice" 2300 "bob" 1800 "charlie"
ZREVRANGE leaderboard 0 2 WITHSCORES   # Top 3 jugadores
ZRANK leaderboard "alice"               # Posición (base 0)
ZINCRBY leaderboard 100 "alice"         # Alice anota 100 puntos

Así es como se construyen a escala las clasificaciones de juegos, las publicaciones en tendencia y las colas de prioridad.

Patrones del mundo real

Patrón 1: Almacenamiento de sesiones

En lugar de sesiones respaldadas por base de datos, usa Redis para búsquedas instantáneas:

import redis
r = redis.Redis()

# Almacenar sesión
r.setex(f"session:{token}", 3600, json.dumps(user_data))

# Recuperar sesión
data = r.get(f"session:{token}")

¿Por qué? Las sesiones en base de datos añaden 1-5 ms por solicitud. Las sesiones en Redis añaden 0,1 ms. Con 1000 req/s, eso supone 5 segundos ahorrados cada segundo.

Patrón 2: Limitación de velocidad

Limitador de velocidad con ventana deslizante en 3 comandos:

# Permitir 100 solicitudes por minuto por usuario
MULTI
INCR rate:user:1001
EXPIRE rate:user:1001 60
EXEC

# Verificar: si el resultado de INCR > 100, rechazar la solicitud

Patrón 3: Caché con cache-aside

El patrón de caché más habitual:

def get_user(user_id):
    # 1. Verificar caché
    cached = redis.get(f"user:{user_id}")
    if cached:
        return json.loads(cached)
    
    # 2. Cache miss → consultar base de datos
    user = db.query("SELECT * FROM users WHERE id = %s", user_id)
    
    # 3. Poblar caché (expirar en 5 minutos)
    redis.setex(f"user:{user_id}", 300, json.dumps(user))
    return user

Patrón 4: Pub/Sub para eventos en tiempo real

Redis Pub/Sub permite mensajería en tiempo real entre servicios:

# Suscriptor (escucha mensajes)
SUBSCRIBE chat:room:42

# Publicador (envía mensajes)
PUBLISH chat:room:42 "¡Hola a todos!"

En código de aplicación:

# Publicador
redis.publish("notifications", json.dumps({
    "type": "new_order",
    "order_id": 12345
}))

# Suscriptor
pubsub = redis.pubsub()
pubsub.subscribe("notifications")
for message in pubsub.listen():
    handle_notification(message)

Patrón 5: Bloqueos distribuidos

Evita condiciones de carrera entre múltiples servidores:

# Adquirir bloqueo (NX = solo si no existe, EX = expirar)
SET lock:invoice:gen "worker-1" NX EX 30

# Liberar bloqueo (solo si eres el propietario — usar script Lua)

Redis Streams — event sourcing y colas de mensajes

Los Streams son la respuesta de Redis a los registros de eventos estilo Kafka:

# Añadir eventos
XADD orders * user_id 1001 product "Widget" qty 3
XADD orders * user_id 1002 product "Gadget" qty 1

# Leer últimos eventos
XRANGE orders - + COUNT 10

# Grupos de consumidores (múltiples trabajadores)
XGROUP CREATE orders processors $ MKSTREAM
XREADGROUP GROUP processors worker-1 COUNT 5 BLOCK 2000 STREAMS orders >

Los Streams te ofrecen registros de eventos persistentes y reproducibles con grupos de consumidores — ideales para la comunicación entre microservicios.

Consejos de rendimiento

1. Usa pipelining para operaciones masivas

En lugar de 100 viajes de ida y vuelta, envía 100 comandos de una vez:

pipe = redis.pipeline()
for i in range(100):
    pipe.set(f"key:{i}", f"value:{i}")
pipe.execute()  # Un solo viaje de ida y vuelta

2. Elige la estructura de datos adecuada

  • ¿Necesitas un contador? → INCR (no GET + SET)
  • ¿Necesitas un objeto? → Hash (no string JSON serializado)
  • ¿Necesitas elementos únicos? → Set (no List + lógica de deduplicación)
  • ¿Necesitas ranking? → Sorted Set (no ordenar tras la consulta)

3. Establece TTL en todo

La memoria es finita. Siempre fija una expiración en las claves de caché:

SET cache:api:result "{...}" EX 300   # TTL de 5 minutos

4. Usa convenciones de nomenclatura para las claves

recurso:id:campo
user:1001:profile
cache:api:v2:products
session:abc123
queue:emails:pending

Persistencia: RDB vs AOF

Redis puede persistir datos en disco para mayor durabilidad:

Modo Cómo funciona Compensación
RDB Instantáneas en un momento dado Recuperación rápida, posible pérdida de datos
AOF Registra cada operación de escritura Más lento, pérdida mínima de datos
Ambos RDB + AOF combinados Mayor durabilidad
# En redis.conf
save 900 1          # Instantánea si 1 clave cambió en 900s
appendonly yes      # Activar AOF
appendfsync everysec  # Fsync cada segundo

Referencia rápida de comandos

¿Necesitas buscar un comando específico de Redis? Usa nuestra Redis Cheat Sheet — cubre más de 200 comandos organizados por estructura de datos con sintaxis, ejemplos y copia con un clic.

Conclusión

Redis es mucho más que un caché. Sus estructuras de datos encajan perfectamente con las necesidades reales de las aplicaciones:

  • Strings → sesiones, contadores, caché simple
  • Hashes → perfiles de usuario, objetos de configuración
  • Lists → colas, feeds de actividad, elementos recientes
  • Sets → etiquetas, visitantes únicos, relaciones
  • Sorted Sets → clasificaciones, rankings, colas de prioridad
  • Streams → event sourcing, colas de mensajes
  • Pub/Sub → notificaciones en tiempo real, chat

Empieza con el caché, pero no te quedes ahí. Redis puede reemplazar varias piezas de infraestructura en tu stack — y hacerlo todo a velocidad inferior al milisegundo.