Es ist eine intergalaktische Wahrheit: Egal wie viel RAM, wie viele CPU-Kerne oder wie schnelle NVMe-Speicher ihr in einen einzelnen Server verbaut – irgendwann reicht die Leistung einfach nicht mehr aus. Oder noch schlimmer: Die Hardware fällt aus. Ein einzelner Computer ist wie der depressive Roboter Marvin aus Per Anhalter durch die Galaxis: Er hat eine Gehirnkapazität von der Größe eines Planeten, aber wenn sein Netzteil durchbrennt, ist das Universum trotzdem offline.
Die Lösung ist das Verteilte System. Laut der Definition von Andrew S. Tanenbaum ist ein Verteiltes System ein Zusammenschluss unabhängiger Computer, der sich für den Benutzer als ein einziges, kohärentes System präsentiert[cite: 1]. Wichtig: Ein Parallelcomputer mit zentralem Speicher, ein simpler Multicore-Prozessor oder ein strikt homogener Rechnercluster ist nach strenger Definition kein verteiltes System[cite: 1].
Peter Löhr formuliert es auf Basis der Prozesse noch grundlegender: Ein verteiltes System ist eine Menge interagierender Prozesse (oder Prozessoren), die über keinen gemeinsamen Speicher verfügen und daher zwingend über Nachrichten (Message Passing) miteinander kommunizieren müssen[cite: 1].
Man teilt sie nach dem Grad der Kopplung in zwei Welten ein[cite: 1]:
Um Prozesse und Lasten in Netzwerken zu verteilen, haben sich drei grundlegende Architekturen etabliert[cite: 1].
Der Klassiker. Die Programme werden strikt in Clients (Anforderer) und Server (Anbieter) unterteilt[cite: 1]. Der Client fordert eine Aufgabe oder ein Betriebsmittel (z. B. Datenbankzugriff oder Rechenleistung) an, der Server antwortet und stellt die Daten bereit[cite: 1]. Dies kann rein auf Software-Ebene geschehen oder als Terminal-Server-System, bei dem der Client-Rechner ohne den Server faktisch nutzlos (ein Dumb-Terminal) ist[cite: 1].
Hier sprechen wir von komplexen Programmen, die durch horizontale Schnitte im Softwareschichtenmodell (Präsentation, Funktion, Daten) auf einzelne, spezialisierte Softwarekomponenten über mehrere Rechner aufgeteilt werden[cite: 1]. * Thin-Client / Aktiver Server: Zentrale Administration und Sicherheit, da die gesamte Logik auf dem Server läuft, der Client übernimmt nur die Präsentation[cite: 1]. * Daten-Server: Der Server liefert nur Rohdaten, der Client übernimmt die Berechnungen (höhere Performance am Endgerät)[cite: 1]. * Fat-Client: Entlastet Server und Netzwerke, da der Client große Teile der Logik und Daten selbst vorhält – schwerer zu warten, aber ausfallsicherer[cite: 1]. Zur Erfüllung der Gesamtaufgabe müssen alle Komponenten über definierte Schnittstellen miteinander kommunizieren[cite: 1].
Das ist die Königsdisziplin. Das Betriebssystem selbst ist auf unzählige Rechner verteilt, was für den Benutzer (und die Anwendung) aber völlig unsichtbar (transparent) geschieht[cite: 1]. * Amoeba: Ein von Andrew S. Tanenbaum an der FU Amsterdam entwickeltes System[cite: 1]. Ziel war es, dem Nutzer die Illusion einer einzigen riesigen Maschine zu geben, auch wenn die physischen Rechner in verschiedenen Ländern stehen[cite: 1]. Fun Fact: Die Programmiersprache Python wurde ursprünglich genau für dieses Betriebssystem entwickelt[cite: 1]! * Banyan VINES: Ein Netzwerkbetriebssystem der 1980er Jahre, basierend auf Unix[cite: 1]. Es implementierte mit „StreetTalk“ einen der ersten Verzeichnisdienste (Directory Services) und gilt als legitimer Vorläufer von Microsofts Active Directory[cite: 1].
Wenn Prozesse auf verschiedenen Maschinen laufen, können sie nicht mehr einfach in dieselbe Variable im RAM schreiben. Sie müssen über das Netzwerk kommunizieren. Dafür gibt es zwei Modelle[cite: 1]: * Synchron: Nachrichten haben hier logisch keine Laufzeit[cite: 1]. Das bedeutet: Der sendende Prozess blockiert (wartet zwingend), bis der Empfang der Nachricht bestätigt ist[cite: 1]. Warten beide, spricht man von einem „Rendezvous“ der Prozesse[cite: 1]. * Asynchron: Prozesse sind entweder aktiv oder passiv[cite: 1]. Ein aktiver Prozess versendet eine Nachricht und rechnet sofort weiter, ohne auf eine Antwort zu warten. Ein passiver Prozess wird erst durch das Eintreffen einer Nachricht reaktiviert[cite: 1].
Das ultimative Praxisbeispiel: Google Google betreibt extrem verteilte Systeme. Die Anfragen wandern völlig transparent für den Endanwender durch ein globales Netz aus Load Balancern, Proxy-Caches, Web-Servern, Index-Servern, Document-Servern und Ad-Servern[cite: 1]. Fällt ein Server aus, merkt ihr davon rein gar nichts, da ein anderer Knoten die Aufgabe übernimmt[cite: 1].
Während verteilte Systeme oft heterogen sind und weite geografische Strecken überbrücken, bezeichnet ein Cluster meist eine Gruppe lokal stark vernetzter, homogener Computer, die nach außen wie ein einziger Supercomputer auftreten[cite: 1]. Historisch begann dies 1977 mit ARCnet und dem ersten großen Erfolg 1983 durch den DEC VAXCluster[cite: 1].
Ein Cluster verfolgt immer mindestens eines von zwei Zielen: Ausfallsicherheit (Hochverfügbarkeit) oder Performance[cite: 1].
Der klassische Hochverfügbarkeits-Cluster besteht aus mindestens zwei Servern (Nodes)[cite: 1]. In einem Aktiv/Passiv-Setup verarbeitet immer nur ein Node aktiv die Daten[cite: 1]. Wer schon einmal abends ab 18:30 Uhr ein Wartungsfenster nutzen musste, um eine redundante Perimeter-Firewall zu rebooten, weiß genau, wie dieses Prinzip in der Netzwerkinfrastruktur funktioniert: Der Datenverkehr schwenkt nahtlos auf die Standby-Appliance um.
Wie wissen die Server voneinander? * Heartbeat: Die Nodes senden in genau definierten Zeitfenstern Datenpakete hin und her[cite: 1]. Bleibt dieses Signal vom aktiven Node aus, weiß der passive Node, dass er die Dienste übernehmen muss[cite: 1]. * Clusterdevices: Das sind gemeinsame Speicherbereiche (z.B. SAN oder replizierter DRBD-Storage), auf die beide Nodes zugreifen können, damit der Datenbestand bei einem Schwenk identisch ist[cite: 1].
Die Split-Brain-Katastrophe und STONITH: Was passiert, wenn nur das Heartbeat-Kabel zwischen den Servern bricht, der aktive Node aber eigentlich noch einwandfrei funktioniert? Der passive Node denkt, der Partner sei tot, und startet die Dienste ebenfalls[cite: 1]. Beide schreiben nun gleichzeitig auf das Clusterdevice – die Daten korrumpieren irreparabel (Split-Brain)[cite: 1]. Die Lösung heißt STONITH (Shoot The Other Node In The Head)[cite: 1]. Bevor der passive Node die Dienste übernimmt, sendet er einen hardwareseitigen Kill-Befehl (z.B. über das IPMI/iLO-Interface oder eine schaltbare PDU-Steckdose) an den aktiven Node, um sicherzustellen, dass dieser wirklich stromlos und tot ist[cite: 1].
Wenn Forscher das Universum simulieren, brauchen sie Rechenpower. HPC-Cluster teilen gewaltige Rechenaufgaben (Jobs) auf[cite: 1]. Ein sogenanntes Decomposition-Programm zerlegt die Aufgabe in kleine Stücke und verteilt sie auf hunderte oder tausende Nodes[cite: 1]. Die Kommunikation zwischen diesen laufenden Job-Teilen geschieht meist über das Message Passing Interface (MPI) in extrem schnellen Netzwerken (wie Infiniband)[cite: 1].
Die Verteilung der Jobs regelt ein Job-Scheduling-Programm, welches nach bestimmten Kategorien (Load Sharing Facility - LSF, oder Network Queueing System - NQS) entscheidet, welcher Node Kapazitäten frei hat[cite: 1]. Heutzutage dominieren Linux-Systeme die TOP500 der Supercomputer, da sie aus günstiger, standardisierter Hardware (COTS - Commercial Off-The-Shelf) gigantische Beowulf-Cluster bilden können[cite: 1].
Hier werden Applikationen (z.B. ein Nginx-Webserver) mehrfach identisch angeboten, um die Gesamtperformance zu steigern[cite: 1]. Ein dedizierter Loadbalancer steht vor den Webservern (Nodes), ermittelt den Auslastungsgrad der einzelnen Server und reicht die Clientanfrage an den Node mit der voraussichtlich besten Performance weiter[cite: 1].
Damit der Loadbalancer selbst nicht zum Single Point of Failure (SPOF) wird, muss er natürlich ebenfalls redundant (als HA-Cluster) ausgelegt sein[cite: 1].
Quellen & Materialien
Dieses Modul basiert auf dem Lehrskript „Betriebssysteme“ der German-Baltic Management School.[cite: 1]