Redis puede hacer que tu aplicación responda 100 veces más rápido sin cambiar una sola línea de tu lógica de negocio. Como caché en memoria, reduce drásticamente las consultas a la base de datos. Esta guía explica cómo funciona y cómo integrarlo con PHP.

¿Qué es Redis?

Redis (Remote Dictionary Server) es un almacén de datos en memoria de código abierto. Opera como una base de datos key-value, caché y message broker. Su superpoder es la velocidad: al operar completamente en RAM, ejecuta millones de operaciones por segundo con latencias de microsegundos.

Instalación y primer contacto

# Instalar en Ubuntu
sudo apt install redis-server
sudo systemctl enable --now redis-server

# Conectar a la CLI
redis-cli

# Operaciones básicas
127.0.0.1:6379> SET saludo "Hola desde Redis"
OK
127.0.0.1:6379> GET saludo
"Hola desde Redis"

# Con expiración (TTL en segundos)
127.0.0.1:6379> SET session:abc123 "user_id:42" EX 3600
OK
127.0.0.1:6379> TTL session:abc123
(integer) 3598

# Verificar si existe una clave
127.0.0.1:6379> EXISTS saludo
(integer) 1

# Eliminar
127.0.0.1:6379> DEL saludo
(integer) 1

Estructuras de datos de Redis

Tipo Comandos clave Caso de uso
String SET, GET, INCR, APPEND Cache, sesiones, contadores
Hash HSET, HGET, HGETALL Perfiles de usuario, objetos
List LPUSH, RPUSH, LRANGE, LPOP Colas de trabajo, actividad reciente
Set SADD, SMEMBERS, SINTER Tags, relaciones sin duplicados
Sorted Set ZADD, ZRANGE, ZRANK Rankings, leaderboards, trending

Caché de consultas MySQL con PHP

get($cacheKey);
    if ($cached !== false) {
        return json_decode($cached, true);
    }

    // 2. No está en caché: consultar la BD
    $stmt = $pdo->prepare(
        'SELECT id, titulo, slug, imagen_portada, vistas, created_at
         FROM articulos WHERE categoria_slug = ? AND estado = "publicado"
         ORDER BY created_at DESC LIMIT 12'
    );
    $stmt->execute([$categoria]);
    $articulos = $stmt->fetchAll(PDO::FETCH_ASSOC);

    // 3. Guardar en caché por 10 minutos
    $redis->setex($cacheKey, 600, json_encode($articulos));

    return $articulos;
}

// Conexión
$redis = new Redis();
$redis->connect('127.0.0.1', 6379);

$articulos = obtenerArticulosPorCategoria($pdo, $redis, 'redes');

// Invalidar caché cuando se publica un nuevo artículo
function invalidarCacheCategoria(Redis $redis, string $categoria): void {
    $redis->del("articulos:categoria:{$categoria}");
    $redis->del("articulos:home");  // también el home
}

Contadores y estadísticas en tiempo real

incr($key);  // O(1) — atómico y ultra rápido

    // Cada 100 vistas, sincronizar con la BD
    if ($vistas % 100 === 0) {
        // Aquí harías el UPDATE a MySQL
    }
}

// Artículos trending (sorted set por vistas en las últimas 24h)
function registrarVistasTrending(Redis $redis, int $articuloId): void {
    $redis->zIncrBy('trending:24h', 1, "articulo:{$articuloId}");
    $redis->expire('trending:24h', 86400);  // expira en 24 horas
}

function obtenerTrending(Redis $redis, int $limit = 10): array {
    return $redis->zRevRange('trending:24h', 0, $limit - 1, true);
    // Retorna artículos ordenados por mayor puntaje
}

Redis con Docker

services:
  redis:
    image: redis:7-alpine
    restart: always
    ports:
      - "127.0.0.1:6379:6379"   # solo accesible desde localhost
    volumes:
      - redis_data:/data
    command: redis-server --appendonly yes --maxmemory 256mb --maxmemory-policy allkeys-lru

volumes:
  redis_data:

"Redis no es una base de datos que reemplaza a MySQL — es el acelerador que hace que MySQL parezca innecesariamente consultado."