Saltar al contenido

Lección 14 de 21 · Lectura y práctica

Implementar una Cola de Trabajos para Procesar Imágenes

Concepto claveUna cola de trabajos es un sistema que permite procesar tareas de manera asíncrona, separando la generación de trabajos de su ejecución. Imagina un restaurante: los clientes piden platos (generan trabajos), la.

Del concepto a la práctica

Taller de esta lección

El procesamiento de imágenes debe transportar metadatos, no depender de un archivo local que solo existe en el productor. En este laboratorio se simula la operación con tamaños y estados; no se modifica ninguna imagen externa. Un ID único permite distinguir reintento de trabajo nuevo.

Ejemplo resuelto

El productor encola {"id":"img-17","ruta":"local/foto-a.jpg","operacion":"miniatura","ancho":320}. El worker valida que ancho sea positivo, cambia el estado a procesando y produce local/foto-a-320.jpg. Si falla antes de producir salida, el ID queda marcado para reintento.

Define explícitamente almacenamiento compartido autorizado o un adaptador de archivos ficticio: local/foto-a.jpg en productor no existe automáticamente en otro host. En la simulación declara origen y salida como registros, sin afirmar transformación de píxeles. Existencia previa de archivo no es una exclusión atómica para workers concurrentes; usa clave/registro de trabajo con estados y salida temporal/publicación controlada. Un lock con TTL puede vencer durante el trabajo; no presenta por sí solo garantía de unicidad de efectos.

Pruébalo

  1. Encola dos imágenes ficticias con anchos 320 y 640.

  2. Consume y valida cada operación.

  3. Simula un fallo en img-17 antes de la salida.

  4. Reintenta usando el mismo ID.

Comprueba tu resultado

Error frecuente: generar una salida duplicada en cada reintento. Corrige comprobando si existe el resultado asociado al ID antes de escribirlo. Resultado esperado: dos trabajos válidos, un reintento identificado y como máximo una salida por combinación de ID y operación.

Diagrama de decisión con ramas Sí y No y un bucle que procesa cada elemento de una lista.
CursaloMapa de práctica
Cómo avanza un programa

Una condición decide qué camino ejecuta el programa. Un bucle repite una operación mientras queden elementos, y termina cuando la lista se agota. Separar ambas ideas ayuda a seguir el flujo y comprobar casos límite.

Ver la infografía en tamaño completo ↗

Concepto clave

Una cola de trabajos es un sistema que permite procesar tareas de manera asíncrona, separando la generación de trabajos de su ejecución. Imagina un restaurante: los clientes piden platos (generan trabajos), la cocina los prepara en orden (procesa trabajos), y los meseros los sirven cuando están listos. En backend, esto evita que operaciones lentas (como procesar imágenes) bloqueen respuestas HTTP rápidas.

Redis es ideal para colas porque ofrece estructuras de datos como listas y conjuntos ordenados, con operaciones atómicas y alta velocidad. Para procesar imágenes, una cola maneja tareas como redimensionar, comprimir o aplicar filtros, liberando al servidor principal para atender más solicitudes. La clave está en la desacoplamiento: el productor (quien crea trabajos) y el consumidor (quien los procesa) no necesitan coordinarse en tiempo real.

Cómo funciona en la práctica

Implementar una cola con Redis para procesar imágenes sigue estos pasos:

  1. Diseñar la estructura de datos: Usa una lista (LPUSH/RPOP) o un conjunto ordenado (ZADD/ZRANGE) para almacenar trabajos. Para prioridades, un conjunto ordenado con timestamps o scores es mejor.
  2. Crear el productor: Cuando un usuario sube una imagen, el backend serializa los datos (ej., ruta del archivo, operaciones a aplicar) y los envía a Redis. Ejemplo con Python y redis-py:
    import redis
    import json
    
    r = redis.Redis(host='localhost', port=6379)
    job = {
        'image_path': '/uploads/photo.jpg',
        'operations': ['resize', 'compress'],
        'priority': 1
    }
    r.lpush('image_queue', json.dumps(job))
  3. Implementar el consumidor: Un worker independiente (puede ser un script o servicio) escucha la cola, procesa trabajos y maneja errores. Usa BRPOP para bloqueo y evitar polling constante:
    while True:
        job_data = r.brpop('image_queue', timeout=30)
        if job_data:
            job = json.loads(job_data[1])
            # Procesar imagen aquí
            print(f"Procesado: {job['image_path']}")
  4. Gestionar resultados y errores: Almacena resultados en otra estructura de Redis (ej., un hash) y reintenta fallos con un contador de intentos.

Caso de estudio

Una plataforma de redes sociales necesita procesar imágenes de perfil subidas por usuarios. Cada imagen debe redimensionarse a tres tamaños (pequeño, mediano, grande) y comprimirse para ahorrar almacenamiento. Sin cola, el servidor se bloquearía durante segundos por cada subida, afectando la experiencia de usuario.

Solución con Redis:

  • Productor: Al subir una imagen, el backend guarda el archivo en disco y envía un trabajo a la cola 'image_processing' con datos como user_id, ruta original y timestamp.
  • Consumidor: Tres workers en paralelo consumen la cola usando BRPOP. Cada worker usa una librería como Pillow para redimensionar y comprimir, luego guarda las versiones en un CDN.
  • Resultados: Los metadatos (ej., URLs de las imágenes procesadas) se almacenan en un hash de Redis con clave user_id para acceso rápido.
En producción, este sistema procesa 10,000 imágenes por hora con latencias menores a 2 segundos por trabajo, mejorando la escalabilidad del backend.

Errores comunes

  • No manejar fallos en el consumidor: Si un worker crashea al procesar un trabajo, este se pierde. Solución: Usar conjuntos ordenados con reintentos o mover trabajos fallidos a una cola de dead-letter.
  • Falta de monitoreo: Ignorar métricas como longitud de la cola o tiempo de procesamiento puede llevar a cuellos de botella. Implementa logging y alertas con herramientas como Redis CLI o Grafana.
  • Serialización incorrecta: Enviar datos binarios directamente a Redis puede causar errores. Siempre serializa con JSON o MessagePack y valida la estructura del trabajo.
  • No escalar workers: Un solo consumidor no basta para cargas altas. Usa múltiples instancias y balancea con BRPOP, que es atómico y seguro para concurrencia.
  • Olvidar limpiar datos: Las colas pueden crecer indefinidamente. Establece políticas de expiración (TTL) o procesos de limpieza para trabajos antiguos.

Checklist de dominio

  • Puedo explicar la diferencia entre procesamiento síncrono y asíncrono usando una analogía del mundo real.
  • He implementado un productor que envía trabajos a una lista de Redis con datos serializados en JSON.
  • He creado un consumidor que procesa trabajos con manejo de errores y reintentos limitados.
  • Sé cómo priorizar trabajos usando conjuntos ordenados de Redis con scores.
  • Puedo monitorear una cola en producción usando comandos como LLEN o ZCARD.
  • He probado la escalabilidad con múltiples workers consumiendo de la misma cola.
  • Entiendo cómo integrar este sistema en un backend existente sin afectar las respuestas HTTP.

Implementa una cola de procesamiento de imágenes con Redis y Python

En este ejercicio, crearás un sistema básico para procesar imágenes de manera asíncrona usando Redis como cola de trabajos. Sigue estos pasos:

  1. Configura el entorno: Instala Redis localmente (puedes usar Docker con docker run -p 6379:6379 redis) y las librerías necesarias en Python (pip install redis Pillow).
  2. Crea el productor: Escribe un script Python que simule la subida de una imagen. Debe:
    • Generar un trabajo con datos como {'image_id': '123', 'action': 'resize', 'dimensions': [100, 100]}.
    • Serializar el trabajo a JSON y enviarlo a una lista de Redis llamada 'image_jobs' usando LPUSH.
    • Ejecutar el script para agregar 5 trabajos a la cola.
  3. Implementa el consumidor: Desarrolla otro script Python que actúe como worker. Debe:
    • Usar BRPOP para consumir trabajos de 'image_jobs' con un timeout de 10 segundos.
    • Al recibir un trabajo, simular el procesamiento imprimiendo un mensaje como "Procesando imagen 123 para resize a 100x100" y esperar 2 segundos (simulando trabajo pesado).
    • Manejar errores: si el trabajo no tiene el campo 'image_id', registrar un fallo y continuar.
  4. Ejecuta y prueba: Corre el consumidor en una terminal y el productor en otra. Verifica que los trabajos se procesen en orden y que no haya pérdidas.
  5. Extiende el sistema: Modifica el consumidor para usar múltiples workers (ej., ejecuta 3 instancias) y observa cómo se distribuyen los trabajos.
Pistas
  • Usa el cliente redis-py: import redis; r = redis.Redis() para conectarte a Redis.
  • Para simular el procesamiento de imágenes, puedes usar time.sleep(2) en lugar de una librería real.
  • Prueba con redis-cli para monitorear la cola usando comandos como LLEN image_jobs.

Evalua tu comprension

Completa el quiz interactivo de arriba para ganar XP.

Sigue con Redis en Producción: Cache, Sesiones y Colas para Backend Engineers

Esta lección forma parte de un curso de Cursalo. Revisa su programa y elige entre la compra individual o el acceso a toda la escuela.

Si ya tenías acceso a este curso, entra con tu cuenta: tus derechos y tu progreso se conservan. No necesitas comprarlo de nuevo.

01 / ELEGIR UNA RUTA

El próximo paso

Aprende IA mientras construyes algo que sí necesitas.

Empieza por el curso inicial o explora el catálogo para encontrar una práctica alineada con tu trabajo.