¿Qué Es el Diseño de Sistemas?
El diseño de sistemas es el proceso de definir la arquitectura, componentes, módulos, interfaces y flujos de datos de un sistema para satisfacer requisitos especificados. Se encuentra en la intersección de la ingeniería de software y la ingeniería de infraestructura, requiriendo que pienses en cómo las piezas individuales de software trabajan juntas a escala para entregar un producto confiable y de alto rendimiento.
Ya sea que estés construyendo un acortador de URLs que maneja unos pocos miles de solicitudes por día o un feed de redes sociales que sirve a miles de millones de usuarios, el pensamiento de diseño de sistemas te ayuda a tomar decisiones informadas de compensación que mantienen tu sistema funcionando sin problemas a medida que crece la demanda.
Por Qué Importa el Diseño de Sistemas
- Escala: Las aplicaciones modernas sirven a millones de usuarios en todo el mundo. Sin un diseño adecuado, un sistema colapsará bajo carga.
- Fiabilidad: El tiempo de inactividad cuesta millones a las empresas. Un buen diseño anticipa fallos y los maneja con gracia.
- Mantenibilidad: Los sistemas sobreviven a los ingenieros que los construyen. Un diseño claro hace que el desarrollo futuro sea más rápido y seguro.
- Eficiencia de Costos: Un mal diseño desperdicia cómputo, almacenamiento y ancho de banda. Una arquitectura inteligente ahorra dinero real.
- Crecimiento Profesional: Las habilidades de diseño de sistemas se evalúan en entrevistas para ingenieros senior y son esenciales para tech leads y arquitectos.
Conceptos Fundamentales del Diseño de Sistemas
Antes de sumergirte en patrones y tecnologías específicas, necesitas una comprensión sólida de las propiedades fundamentales que todo sistema distribuido debe esforzarse por lograr. Estos son los pilares contra los cuales se evalúa cada decisión de diseño.
1. Escalabilidad
La escalabilidad es la capacidad de un sistema para manejar una cantidad creciente de trabajo agregando recursos. Un sistema escalable puede acomodar una mayor demanda sin cambios significativos en su arquitectura.
- Escalado Vertical (Scale Up): Agregar más CPU, RAM o almacenamiento a una máquina existente. Simple pero limitado por los techos del hardware.
- Escalado Horizontal (Scale Out): Agregar más máquinas para distribuir la carga. Más complejo pero virtualmente ilimitado y más tolerante a fallos.
La idea clave es que el escalado horizontal casi siempre se prefiere para sistemas a gran escala porque ninguna máquina individual, por poderosa que sea, puede manejar el tráfico de servicios como Netflix o Google.
2. Fiabilidad
Un sistema fiable continúa funcionando correctamente incluso cuando los componentes fallan. En sistemas distribuidos, los fallos no son excepciones — son la norma. Los discos duros fallan, los paquetes de red se pierden y centros de datos enteros pueden quedar fuera de línea. Un sistema fiable está diseñado para tolerar estos fallos sin perder datos o volverse inaccesible.
Las técnicas para mejorar la fiabilidad incluyen redundancia (ejecutar múltiples copias de servicios), replicación (mantener copias de datos en múltiples ubicaciones) y aislamiento de fallos (asegurar que un fallo en un componente no se propague a otros).
3. Disponibilidad
La disponibilidad mide la proporción del tiempo que un sistema está operativo y accesible. Típicamente se expresa como un porcentaje, a menudo referido como "nueves" de disponibilidad.
Niveles de Disponibilidad
| Disponibilidad | Tiempo de inactividad por año | Tiempo de inactividad por mes |
|---|---|---|
| 99% (dos nueves) | 3.65 días | 7.31 horas |
| 99.9% (tres nueves) | 8.77 horas | 43.83 minutos |
| 99.99% (cuatro nueves) | 52.60 minutos | 4.38 minutos |
| 99.999% (cinco nueves) | 5.26 minutos | 26.30 segundos |
Pasar de tres nueves a cuatro nueves es dramáticamente más difícil y costoso que ir de dos nueves a tres. Cada nueve adicional típicamente requiere una inversión significativa en ingeniería de redundancia, monitoreo y conmutación automática por error.
4. Mantenibilidad
La mantenibilidad abarca lo fácil que es corregir errores, agregar nuevas funcionalidades y operar el sistema día a día. Un sistema mantenible tiene abstracciones limpias, buena documentación, monitoreo integral y pipelines de despliegue automatizados.
Los tres aspectos de la mantenibilidad son operabilidad (hacer fácil para los equipos de operaciones mantener el sistema funcionando), simplicidad (eliminar complejidad innecesaria para que nuevos ingenieros puedan entender el sistema) y evolucionabilidad (hacer fácil cambiar el sistema a medida que evolucionan los requisitos).
5. Latencia y Rendimiento
La latencia es el tiempo que tarda una sola solicitud en viajar del cliente al servidor y de vuelta. El rendimiento es el número de solicitudes u operaciones que un sistema puede manejar por unidad de tiempo. Estas dos métricas a menudo tienen una relación inversa — optimizar una puede perjudicar la otra.
Números de Latencia que Todo Ingeniero Debe Conocer
- Referencia caché L1: 0.5 ns
- Referencia caché L2: 7 ns
- Referencia memoria principal: 100 ns
- Lectura aleatoria SSD: 150 microsegundos
- Búsqueda HDD: 10 ms
- Ida y vuelta dentro del mismo datacenter: 0.5 ms
- Ida y vuelta California a Países Bajos: 150 ms
Marco para Entrevistas de Diseño de Sistemas
Las entrevistas de diseño de sistemas evalúan tu capacidad para diseñar sistemas a gran escala bajo ambigüedad. Tener un marco estructurado te ayuda a mantenerte organizado y cubrir todos los aspectos críticos dentro del límite de tiempo (típicamente 35-45 minutos).
Paso 1: Clarificar Requisitos (5 minutos)
Nunca saltes directamente a la solución. Comienza haciendo preguntas para entender el alcance. Hay dos tipos de requisitos a identificar:
- Requisitos Funcionales: ¿Qué debe hacer el sistema? ¿Cuáles son las funcionalidades principales? Por ejemplo, para un acortador de URLs: crear URLs cortas, redirigir a URLs originales, alias personalizados, analíticas.
- Requisitos No Funcionales: ¿Cómo debe rendir el sistema? Esto incluye objetivos de latencia, requisitos de disponibilidad, necesidades de consistencia y escala esperada.
Paso 2: Estimar la Escala (3 minutos)
Los cálculos aproximados te ayudan a entender el orden de magnitud con el que estás lidiando. Números clave a estimar:
- Usuarios activos diarios (DAU)
- Ratio de lectura a escritura
- Consultas por segundo (QPS)
- Requisitos de almacenamiento a lo largo del tiempo
- Necesidades de ancho de banda
// Ejemplo: Estimando escala para un acortador de URLs
// Suposiciones:
// - 100 millones de URLs creadas por mes
// - Ratio Lectura:Escritura = 100:1
// Escrituras por segundo:
// 100M / (30 días * 24 horas * 3600 segundos) ≈ 40 URLs/seg
// Lecturas por segundo:
// 40 * 100 = 4,000 redirecciones/seg
// Almacenamiento (5 años):
// Cada registro de URL ≈ 500 bytes
// 100M * 12 meses * 5 años * 500 bytes = 3 TB
Paso 3: Diseño de Alto Nivel (10 minutos)
Dibuja los componentes principales en una pizarra o diagrama. Comienza con clientes, balanceadores de carga, servidores de aplicación, bases de datos y cachés. Dibuja el flujo de datos entre ellos. Esto le da a tu entrevistador una vista panorámica de tu arquitectura antes de que profundices en los detalles.
Paso 4: Inmersión Profunda (15 minutos)
El entrevistador te pedirá que profundices en componentes específicos. Aquí es donde tu conocimiento de bases de datos, caché, colas de mensajes y otra infraestructura entra en juego. Prepárate para discutir:
- Esquema de base de datos y elección de SQL vs NoSQL
- Diseño de API (REST, GraphQL, gRPC)
- Estrategias de particionamiento y replicación de datos
- Capas de caché e invalidación
- Cómo el sistema maneja los fallos
Paso 5: Cierre (5 minutos)
Resume tu diseño, discute las compensaciones que hiciste, identifica posibles cuellos de botella y sugiere mejoras futuras. Esto demuestra madurez y conciencia de que ningún diseño es perfecto.
Métricas Clave y SLAs
Los Acuerdos de Nivel de Servicio (SLAs) definen el comportamiento esperado de tu sistema. Son contratos entre tú y tus usuarios. Aquí están las métricas más importantes:
- SLI (Indicador de Nivel de Servicio): Una medida cuantitativa del servicio, como latencia de solicitud, tasa de error o rendimiento.
- SLO (Objetivo de Nivel de Servicio): Un valor objetivo para un SLI, como "latencia del percentil 99 por debajo de 200ms."
- SLA (Acuerdo de Nivel de Servicio): Un contrato formal con consecuencias (usualmente financieras) si los SLOs no se cumplen.
- Presupuesto de Errores: La cantidad de tiempo de inactividad o errores permitidos antes de que se viole un SLO. Los equipos usan presupuestos de errores para equilibrar la fiabilidad con la velocidad de desarrollo de funcionalidades.
Cómo Abordar Cualquier Problema de Diseño de Sistemas
Más allá del marco de entrevistas, aquí hay un modelo mental para abordar desafíos de diseño del mundo real:
- Empieza simple. Comienza con una arquitectura de un solo servidor que maneje todo. Esta es tu línea base.
- Identifica cuellos de botella. A medida que escales, encuentra el componente que fallará primero — generalmente la base de datos o un punto único de fallo.
- Aplica patrones conocidos. Usa balanceadores de carga, cachés, colas de mensajes, CDNs y replicación de bases de datos para abordar cuellos de botella específicos.
- Piensa en modos de fallo. ¿Qué pasa si un servidor se cae? ¿Si la base de datos falla? ¿Si ocurre una partición de red?
- Considera la complejidad operativa. Un sistema que requiere un doctorado para operar no es un buen sistema. Las arquitecturas más simples son más fáciles de depurar y mantener.
- Haz las compensaciones explícitas. Cada decisión tiene pros y contras. Documéntalas y prepárate para justificar tus elecciones.
Errores Comunes en el Diseño de Sistemas
- Sobreingeniería: Diseñar para la escala de Google cuando tienes 100 usuarios. Comienza con lo que necesitas hoy y planifica para lo que podrías necesitar mañana.
- Ignorar requisitos: Saltar a la solución antes de entender el problema lleva a construir algo equivocado.
- Punto único de fallo: Si un solo componente que falla derriba todo el sistema, tu diseño es frágil.
- Descuidar el monitoreo: Si no puedes observar tu sistema, no puedes arreglarlo cuando las cosas van mal.
- Olvidar los datos: Los sistemas viven y mueren por sus datos. Cómo se almacenan, replican, particionan y acceden los datos determina el comportamiento del sistema.