Sistemas distribuidos: qué son y cómo funcionan

Qué son los sistemas distribuidos, sus características y tipos (cliente-servidor, P2P, microservicios o grid) y los retos de CAP, consenso y tolerancia a fallos.

Ficha dorada de ajedrez frente a un grupo de fichas plateadas conectadas entre sí por flechas doradas sobre una superficie oscura

Un sistema distribuido es un conjunto de computadoras independientes que se comunican a través de una red y coordinan su trabajo para ofrecer un servicio que, desde fuera, se percibe como uno solo. No comparten memoria ni un reloj común: se entienden enviándose mensajes y asumen que cualquiera de sus nodos puede fallar sin que el conjunto deje de funcionar. La computación en la nube, una base de datos replicada, una aplicación de microservicios o una red de intercambio de ficheros son sistemas distribuidos.

La idea es sencilla de enunciar y difícil de llevar a la práctica: cuando el trabajo se reparte entre muchas máquinas conectadas aparecen problemas que no existen en un único servidor —particiones de red, relojes desincronizados, fallos parciales— y un puñado de teoremas que marcan los límites de lo posible. Repasamos sus características, ventajas y retos, los tipos principales, la escalabilidad, la tolerancia a fallos y ejemplos reales, con fuentes primarias como el NIST y los trabajos clásicos de la computación distribuida.

Qué es un sistema distribuido

La definición clásica de Andrew Tanenbaum describe un sistema distribuido como una colección de computadoras independientes que, para el usuario, aparecen como un único sistema coherente. La clave está en esa apariencia: por debajo hay muchas máquinas, pero el usuario no debería notar dónde se ejecuta cada tarea ni en qué nodo viven los datos.

De esa definición se derivan tres condiciones que se repiten en cualquier sistema distribuido:

  • Componentes autónomos. Cada nodo es una computadora con su propio procesador y su propia memoria; ninguno controla a los demás de forma absoluta.
  • Comunicación por red. La única forma de coordinarse es intercambiar mensajes. No hay una memoria compartida a la que todos accedan, y ese envío de mensajes nunca es instantáneo ni garantizado.
  • Objetivo común. Los nodos colaboran para prestar un servicio —almacenar datos, calcular, atender peticiones— que ninguno ofrece por separado.

Conviene distinguirlo de otras ideas con las que se confunde a menudo. Un sistema centralizado concentra todo en una máquina o un único punto de control. Un programa concurrente dentro de un mismo ordenador usa varios hilos o núcleos, pero comparte la misma memoria física. Lo distribuido es otra cosa: hay varios ordenadores separados, sin reloj único y con una red frágil entre ellos. Esa distancia es precisamente lo que da las ventajas y también lo que introduce la complejidad.

Características de un sistema distribuido

Más allá de la definición, hay una serie de propiedades que explican por qué diseñarlos es distinto a programar una sola máquina.

  • Concurrencia real. Varios nodos ejecutan tareas a la vez, a menudo sobre los mismos datos. Coordinar ese acceso simultáneo es el problema central.
  • Ausencia de reloj global. Cada máquina marca una hora distinta: no existe un «ahora» único, así que el orden de los eventos hay que reconstruirlo.
  • Comunicación por mensajes. Los nodos no comparten variables; se envían información que puede retrasarse, perderse, duplicarse o llegar desordenada.
  • Fallos parciales. Una parte puede caerse mientras el resto sigue operando; el sistema no está «vivo o muerto», sino en un estado intermedio permanente.
  • Transparencia. El sistema oculta su complejidad: de acceso (usar un recurso remoto como si fuera local), de ubicación, de replicación y de fallo.
  • Heterogeneidad. Es habitual mezclar hardware, sistemas operativos y proveedores distintos, lo que obliga a interfaces y protocolos comunes.
  • Escalabilidad y descentralización. El objetivo es crecer añadiendo recursos sin rehacer los cimientos y sin un único punto cuyo fallo detenga el conjunto.

Estas propiedades son también la lista de problemas a resolver. La transparencia de fallo no es un dato de partida, sino un objetivo que se consigue con réplicas, reintentos y consenso; y la ausencia de reloj global obliga a construir un orden lógico de los acontecimientos.

Ventajas de los sistemas distribuidos

Si distribuir complica tanto las cosas, ¿por qué se hace? Porque resuelve problemas que una sola máquina no puede atender bien.

  • Más rendimiento y capacidad. El trabajo se reparte entre muchos nodos, que en conjunto suman más potencia que cualquier equipo aislado.
  • Alta disponibilidad y aislamiento de fallos. Si un nodo cae, otros asumen su función; un problema localizado no arrastra a todo el sistema.
  • Escalabilidad bajo demanda. Se añaden o quitan recursos según la carga, algo imposible cuando todo depende de un servidor físico con límites fijos.
  • Proximidad al usuario. Con nodos en distintas regiones se reduce la latencia para quien está lejos del centro de datos principal.
  • Mejor relación coste/rendimiento. Muchos equipos de gama media salen más baratos que una máquina de gama altísima, y se sustituyen de uno en uno.
  • Flexibilidad y evolución. Los componentes se pueden actualizar o reescribir por separado, sin detener el conjunto.

Las plataformas de computación en la nube son el ejemplo más visible de estas ventajas: entregan, precisamente, la elasticidad y la distribución geográfica que una infraestructura propia difícilmente iguala. Ese mismo éxito es el que ha llevado a que hoy casi cualquier servicio relevante sea, por dentro, un sistema distribuido.

Retos y limitaciones

La cara amable de distribuir tiene un reverso técnico bien documentado. La mayoría de los dolores de cabeza nace de una realidad incómoda: la red no es fiable y los nodos no comparten un estado perfecto.

El teorema CAP

El teorema CAP es el punto de partida de cualquier discusión sobre consistencia. Formulado por Eric Brewer en el año 2000 y demostrado formalmente por Seth Gilbert y Nancy Lynch en 2002, afirma que un sistema distribuido no puede garantizar a la vez estas tres propiedades:

  • Consistencia (Consistency): toda lectura recibe la última escritura confirmada, como si hubiera una sola copia de los datos.
  • Disponibilidad (Availability): toda petición recibe una respuesta, aunque algún nodo esté caído.
  • Tolerancia a particiones (Partition tolerance): el sistema sigue funcionando aunque la red se parta en dos mitades que no se comunican.

Como las particiones de red acaban ocurriendo tarde o temprano, la tolerancia a particiones se da por hecha, y la disyuntiva real es entre consistencia y disponibilidad durante la partición. Un sistema CP prefiere rechazar peticiones antes que devolver datos desactualizados; un sistema AP sigue respondiendo aunque el resultado pueda ser viejo y se reconcilie después. Ninguna elección es «mejor»: depende de si el negocio tolera un dato obsoleto (un «me gusta» de menos) o un servicio detenido (un pago que no se completa).

El modelo se amplió con PACELC (Daniel Abadi, 2012): cuando no hay partición (Else), también hay que elegir entre latencia y consistencia. Coordinar nodos para dar una respuesta coherente cuesta tiempo; relajarlo da respuestas más rápidas. Por eso no basta con decir «somos CP o AP», porque en funcionamiento normal las decisiones de latencia pesan igual o más.

Consistencia y consenso

Consenso es que varios nodos se pongan de acuerdo en un mismo valor —quién es el líder, en qué orden van las operaciones, si una transacción está confirmada— incluso si algunos fallan o los mensajes se pierden. Es la pieza sobre la que se construye la consistencia, y tiene límites teóricos conocidos: el resultado de Fischer, Lynch y Paterson demuestra que, en un modelo puramente asíncrono, no existe un algoritmo determinista que garantice consenso si un solo proceso puede fallar. En la práctica se sortea con timeouts, que reintroducen cierta sincronía.

Los dos algoritmos de consenso más estudiados son Paxos, descrito por Leslie Lamport y considerado durante años difícil de implementar, y Raft, diseñado por Diego Ongaro y John Ousterhout con la comprensibilidad como objetivo explícito. Ambos se apoyan en un quórum —mayoría de nodos— para decidir y sobrevivir a caídas minoritarias.

Otra pieza fundamental viene de mucho antes: el trabajo de Lamport de 1978 sobre relojes lógicos demostró que, sin un reloj común, el orden de los acontecimientos se puede reconstruir con la relación «ocurrió antes» y con marcas de tiempo lógicas. De ahí bebieron después las bases de datos y los sistemas de mensajería para decidir qué versión de un dato es la más reciente.

La alternativa a la consistencia fuerte es la consistencia eventual: si dejan de llegar escrituras, todas las réplicas acaban coincidiendo. Es el modelo habitual en sistemas AP; a cambio de aceptar lecturas temporalmente desfasadas, se gana disponibilidad y velocidad.

Latencia, particiones y fallos parciales

En una sola máquina, o funciona o se apaga. En un sistema distribuido, una parte falla mientras el resto sigue vivo, y esa ambigüedad es la fuente de casi todos los errores difíciles: no se sabe si un nodo está lento, caído o incomunicado. Peter Deutsch y James Gosling resumieron en las falacias de la computación distribuida las suposiciones que todo el mundo hace y que son falsas: que la red es fiable, que la latencia es cero, que el ancho de banda es infinito, que la red es segura, que la topología no cambia, que hay un administrador, que el coste de transporte es cero y que la red es homogénea.

De ahí nacen problemas concretos de diseño: mensajes duplicados que provocan operaciones repetidas, respuestas que llegan después de que el cliente haya dado por perdida la petición, relojes que se desajustan y hacen parecer que un evento posterior ocurrió antes. La respuesta habitual es diseñar operaciones idempotentes (repetirlas no cambia el resultado) y aceptar que el sistema operará en un estado de incertidumbre permanente.

Complejidad operativa y seguridad

Cada nodo es también un punto que hay que instalar, parchear, monitorizar y proteger. La superficie de ataque crece con el número de componentes y con las comunicaciones internas, que a menudo quedan menos vigiladas que el perímetro. A esto se suma el coste de observabilidad: entender qué pasó en una petición que cruzó quince servicios exige instrumentación específica, porque un registro por máquina ya no cuenta la historia completa.

Tipos de sistemas distribuidos

No hay un único modelo. Los más habituales se diferencian por cómo reparten el trabajo y por dónde vive el control.

Cliente-servidor

Es el más tradicional y sencillo: varios clientes piden y uno o varios servidores responden, almacenan los datos o ejecutan el servicio. El cliente inicia la conversación y el servidor la atiende. Es la base de la web, del correo y de la mayoría de aplicaciones empresariales.

Su variante más extendida es la arquitectura en capas: una capa de presentación (la interfaz), una de lógica de negocio y una de datos. Separarlas permite escalar cada una por separado y sustituir la interfaz sin tocar la base de datos. El inconveniente clásico es que el servidor puede convertirse en un cuello de botella o en un punto único de fallo si no se replica.

Peer-to-peer (P2P)

Aquí no hay clientes ni servidores fijos: cada nodo es a la vez consumidor y proveedor. Los pares (peers) se conectan entre sí y comparten recursos —ficheros, ancho de banda, capacidad— sin una autoridad central. Existen redes no estructuradas, donde los nodos se descubren al azar, y estructuradas, que organizan el contenido en tablas de hash distribuidas (DHT) para localizar cada recurso de forma eficiente.

BitTorrent es el ejemplo más conocido del intercambio de ficheros; las cadenas de bloques llevan el concepto al extremo, con una red de nodos que mantiene un registro replicado y sin dueño. La ventaja es la resistencia a caídas y la capacidad de crecer con cada participante; el reto, la dificultad de garantizar identidad, confianza y cumplimiento normativo.

Microservicios

En lugar de una aplicación monolítica, el sistema se divide en servicios pequeños e independientes, cada uno con su responsabilidad, que se comunican por red mediante APIs. Se despliegan por separado, se escalan por separado y pueden estar escritos en tecnologías distintas. Los contenedores y orquestadores como Kubernetes son la infraestructura habitual para gestionarlos.

Aportan agilidad y aislamiento de fallos, y permiten que equipos distintos trabajen sin pisarse. La contrapartida es la complejidad: más servicios significa más puntos de fallo, más latencia acumulada y la necesidad de trazabilidad, contratos de API estables y automatización madura. Un monolito bien modularizado suele ser mejor opción en proyectos pequeños.

Grid y clústeres

Un clúster agrupa máquinas similares, normalmente en el mismo lugar, para comportarse como una sola máquina potente o como un servicio redundante. Un grid (rejilla) va más allá: conecta recursos heterogéneos y geográficamente dispersos, a menudo cedidos por distintas organizaciones, para resolver cálculos muy costosos. El ejemplo clásico son los proyectos de cómputo voluntario, en los que miles de ordenadores repartidos por el mundo donan tiempo de proceso para analizar datos científicos.

La diferencia esencial es la homogeneidad y la cercanía: el clúster es uniforme y local; el grid es variado, remoto y tolerante a que los nodos entren y salgan. La nube actual combina rasgos de ambos, con recursos de centros de datos distribuidos que se aprovisionan como si fueran un único pool.

Tipo Cómo reparte el trabajo Ejemplo típico Reto principal
Cliente-servidor Clientes piden, servidor atiende Aplicación web con base de datos Cuello de botella y punto único de fallo
P2P Todos los nodos piden y sirven BitTorrent, cadenas de bloques Confianza, identidad y cumplimiento
Microservicios Servicios autónomos por API Plataforma en contenedores Complejidad operativa y trazabilidad
Clúster Máquinas similares y cercanas Servicio de alta disponibilidad Coordinar el estado compartido
Grid Recursos dispersos y heterogéneos Cómputo científico distribuido Gestión de nodos que entran y salen

Escalabilidad: crecer sin romperse

La escalabilidad es la capacidad de absorber más carga añadiendo recursos sin degradar el servicio. Se consigue por dos caminos que conviene no confundir:

  • Escalado vertical. Se da más potencia a la máquina existente: más memoria, más núcleos, discos más rápidos. Es sencillo hasta que se alcanza el techo del hardware disponible y suele encarecerse de forma desproporcionada.
  • Escalado horizontal. Se añaden más máquinas o nodos y el trabajo se reparte entre ellos. Es la vía propia de los sistemas distribuidos: crece casi sin límite teórico a cambio de tener que coordinar todos esos nodos.

Para que el escalado horizontal funcione hacen falta varias técnicas combinadas:

  • Balanceo de carga. Un componente reparte las peticiones entrantes entre los nodos disponibles para que ninguno se sature.
  • Almacenamiento en caché. Guardar datos muy consultados o resultados ya calculados evita repetir trabajo costoso. La memoria caché es la misma idea aplicada dentro de cada servidor.
  • Particionado o sharding. Los datos se dividen en fragmentos y cada nodo se ocupa de los suyos, de modo que la carga no depende de una única base de datos.
  • Replicación. Cada dato tiene varias copias en nodos distintos, lo que reparte las lecturas y permite sobrevivir a caídas.
  • Escalado automático. Reglas o métricas añaden y retiran nodos según la demanda, de modo que el sistema aguanta los picos y ahorra cuando baja la actividad.
  • Servicios sin estado. Si un nodo no guarda datos propios entre peticiones, cualquiera puede atender la siguiente; basta con replicar el estado en un almacén común.

Más allá de crecer en máquinas, conviene distinguir dos dimensiones. La escalabilidad geográfica reparte nodos por regiones sin que crezca el tiempo de comunicación entre ellos, para atender a usuarios de todo el mundo. La administrativa mide la dificultad de gestionar el sistema a medida que crece: cuantos más nodos, más complejo es operarlos, y una arquitectura que no lo tenga en cuenta acaba siendo ingobernable aunque técnicamente escale. Esa parte se apoya en automatización, estandarización y herramientas de gestión centralizada.

Tolerancia a fallos y alta disponibilidad

Un sistema distribuido serio asume que algo se va a romper. La tolerancia a fallos es la capacidad de seguir prestando el servicio, o de degradarlo con elegancia, cuando un componente falla. Estas son las estrategias más habituales:

  • Redundancia y replicación. Cada función crítica existe por duplicado en nodos distintos, de modo que la caída de uno no deja el servicio sin respuesta.
  • Conmutación por fallo (failover). Un nodo de reserva detecta que el principal ha caído y toma el relevo, a menudo decidido mediante consenso y quórum para evitar dos líderes a la vez.
  • Detección de fallos. Los nodos se vigilan con latidos periódicos (heartbeats); si dejan de llegar, se declara al emisor sospechoso. Como no se puede distinguir con certeza un nodo lento de uno caído, se usan tiempos de espera ajustados al caso de uso.
  • Reintentos idempotentes. Ante un fallo de red se repite la operación; si está diseñada para ser idempotente, repetirla no genera efectos dobles.
  • Cortacircuitos (circuit breaker). Si un servicio dependiente falla repetidamente, se deja de llamarlo durante un tiempo para no propagar el fallo en cascada.
  • Degradación elegante. Cuando una parte no está disponible, el sistema ofrece una versión reducida del servicio en lugar de caerse entero.

La disponibilidad se planifica con dos métricas complementarias: el RTO (tiempo máximo que se admite estar caído antes de recuperar el servicio) y el RPO (cantidad máxima de datos que se admite perder en forma de última escritura no replicada). Ambas fijan cuánta redundancia hace falta y a qué coste. También es común validar el diseño provocando fallos a propósito —la disciplina conocida como chaos engineering— para comprobar que el sistema reacciona como se espera antes de que falle de verdad.

Ejemplos reales

Los sistemas distribuidos no son un tema académico: sostienen buena parte de la infraestructura que usamos a diario.

  • El sistema de nombres de dominio (DNS). Es una base de datos jerárquica y distribuida por todo el mundo que traduce nombres a direcciones IP. Ningún servidor conoce todos los dominios: cada uno delega en los demás.
  • Bases de datos distribuidas. Sistemas como Apache Cassandra reparten y replican datos entre muchos nodos; otros, como Google Spanner, combinan distribución global con consistencia fuerte apoyándose en relojes sincronizados. Detrás de muchas de estas ideas están los modelos de replicación de Amazon Dynamo y Google Bigtable.
  • Sistemas de ficheros distribuidos. El sistema de ficheros de Hadoop (HDFS) y su antecesor GFS parten los ficheros en bloques y los replican en varias máquinas para procesar grandes volúmenes de datos.
  • Microservicios en la nube. Una aplicación moderna se compone de decenas de servicios en contenedores orquestados por Kubernetes, que los distribuye, los reinicia si fallan y los escala según la carga.
  • Plataformas de mensajería. Sistemas como Apache Kafka distribuyen flujos de eventos entre nodos para que productores y consumidores no dependan de un único proceso.
  • Redes P2P. BitTorrent reparte la descarga de un fichero entre todos los participantes, y las cadenas de bloques mantienen un registro replicado sin autoridad central.
  • Telefonía móvil. Las redes de telefonía combinan terminales, sistemas de conmutación y servicios basados en Internet para compartir la carga de las llamadas y los datos.
  • Comercio electrónico. Una compra desencadena una cadena de interacciones distribuidas: la tienda, el sistema de pago, la entidad financiera y la logística intercambian información sin que ningún nodo controle todo el proceso.

En el fondo, todos comparten el mismo patrón: dividir el trabajo, replicar lo crítico y coordinar los nodos con protocolos que asumen que la red y algunos componentes fallarán. Las redes que los conectan —y protocolos como TCP/IP— son la base sobre la que se levanta todo lo demás.

Cómo se diseñan y operan

Diseñar un sistema distribuido obliga a programar para un mundo en el que la red no es fiable y los nodos fallan de forma impredecible. Estas prácticas marcan la diferencia:

  • Diseñar para el fallo. Las decisiones de consistencia y disponibilidad se toman de forma explícita, no por accidente.
  • Idempotencia y reintentos con espera creciente. Repetir una petición debe ser seguro, y los reintentos conviene espaciarlos con algo de aleatoriedad.
  • Tiempos de espera y cortacircuitos. Toda llamada entre servicios necesita un límite máximo para que un componente lento no arrastre a los demás.
  • Observabilidad. Métricas, registros y trazas distribuidas que sigan una petición a través de todos los servicios; sin esa visibilidad, diagnosticar un fallo es adivinar.
  • Automatización y seguridad por capas. Infraestructura como código y despliegues reproducibles, con mínimo privilegio y cifrado entre servicios.

Conclusión

Un sistema distribuido reparte el trabajo entre computadoras independientes que se coordinan por red para ofrecer un servicio único. Sus ventajas —escalabilidad, disponibilidad, proximidad al usuario y mejor coste— explican por qué dominan la infraestructura actual, y sus retos —el teorema CAP, la necesidad de consenso, la latencia y los fallos parciales— definen los límites de lo que se puede prometer. Entender ese equilibrio es la diferencia entre creer que basta con «poner más servidores» y diseñar de verdad un sistema que resista cuando algo se rompe.

Preguntas frecuentes

¿Qué diferencia hay entre un sistema distribuido y uno centralizado?

En un sistema centralizado todo el procesamiento y el estado dependen de una única máquina o un único punto de control. En uno distribuido hay varios nodos autónomos que se comunican por red y comparten el trabajo. El centralizado es más sencillo de operar, pero tiene un límite de capacidad claro y un punto único de fallo; el distribuido escala y resiste mejor, a cambio de mucha más complejidad.

¿El teorema CAP obliga a elegir siempre dos de tres?

Con matices. Como las particiones de red terminan ocurriendo, la tolerancia a particiones se asume y la elección real se plantea solo durante la partición: entre mantener la consistencia o la disponibilidad. Cuando la red funciona con normalidad, el modelo PACELC recuerda que queda otra disyuntiva cotidiana, entre consistencia y latencia.

¿Qué es la consistencia eventual?

Es un modelo en el que, si dejan de producirse escrituras, todas las réplicas acaban teniendo el mismo valor, pero durante un tiempo pueden devolver versiones distintas. A cambio de aceptar lecturas temporalmente desfasadas, el sistema gana disponibilidad y rapidez, por lo que es habitual en arquitecturas tolerantes a particiones.

¿Un clúster es lo mismo que un sistema distribuido?

No exactamente. Un clúster es un caso concreto: máquinas similares, normalmente cercanas, que trabajan juntas como una sola. Un sistema distribuido es un concepto más amplio que incluye clústeres, pero también grids, redes P2P, microservicios repartidos por regiones y cualquier conjunto de nodos autónomos que cooperan por red.

¿Qué es un fallo bizantino?

Es el fallo de un nodo que no se limita a caerse, sino que actúa de forma arbitraria o maliciosa: envía información falsa o contradictoria a distintos nodos. Los algoritmos de consenso tolerantes a fallos bizantinos, como los derivados del problema de los generales bizantinos planteado por Lamport, Shostak y Pease, pueden mantener el sistema en pie siempre que la mayoría de nodos sea honesta.

Fuentes