Im Zusammenhang mit Software versteht man unter Skalierbarkeit ein System aus Hard- und Software, dessen Leistung durch das Hinzufügen von Ressourcen oder weiteren Knoten/Rechnern in einem definierten Bereich proportional (bzw. linear) zunimmt.

Eine allgemein gültige Definition dieses Begriffs ist allerdings nicht trivial[1]. Es ist erforderlich, für den jeweiligen speziellen Fall, stets einen Bereich anzugeben. (Z.B. muss ein System bei 100 gleichzeitigen Zugriffen nicht zwangsläufig gleich gut skalieren wie bei 100.000 Zugriffen)

Ressourcen können z.B. sein: CPU, RAM, Festplatten, Netzwerk-Bandbreite,...

Die Skalierbarkeit eines Systems wird mit dem Skalierungsfaktor (auch SpeedUp genannt) angegeben.

vertikale vs. horizontale Skalierung Bearbeiten

Man kann die Leistung eines Systems auf zwei verschiedene Arten steigern:[2]

vertikale Skalierung (scale up) Bearbeiten

Unter vertikaler Skalierung versteht man ein steigern der Leistung durch das Hinzufügen von Ressourcen zu einem Knoten/Rechner des Systems. Beispiele dafür wären das Vergrößern von Speicherplatz, das Hinzufügen einer CPU, oder das Einbauen einer leistungsstärkeren Grafikkarte.

Charakteristisch für diese Art von Skalierung ist, dass ein System unabhängig von der Implementierung der Software schneller gemacht werden kann. Das heißt, es muss keine Zeile Code geändert werden, um eine Leistungssteigerung durch vertikales Skalieren zu erfahren. Der große Nachteil dabei ist jedoch jener, dass man früher oder später auf ein Limit stößt, bei dem man den Rechner nicht mehr aufrüsten kann, wenn man bereits die beste Hardware verwendet die zu diesem Zeitpunkt am Markt ist.

horizontale Skalierung (scale out) Bearbeiten

Im Gegensatz zur vertikalen Skalierung sind der horizontalen Skalierung keine Grenzen (aus Sicht der Hardware) gesetzt. Horizontale Skalierung bedeutet die Steigerung der Leistung eines Systems durch das Hinzufügen zusätzlicher Rechner/Knoten. Die Effizienz dieser Art der Skalierung ist jedoch stark von der Implementierung der Software abhängig, da nicht jede Software gleich gut parallelisierbar ist.

Skalierungsfaktor Bearbeiten

Der Skalierungsfaktor (SpeedUp) beschreibt den tatsächlich Leistungszuwachs einer zusätzlichen Ressourcen-Einheit. Z.B. kann eine zweite CPU 90% zusätzliche Leistung bringen. Grundsätzlich unterscheidet man 3 Arten von Skalierbarkeit:

Von einer super-linearen Skalierbarkeit spricht man, wenn der Skalierungsfaktor beim Hinzufügen von Ressourcen größer wird.

Lineare Skalierbarkeit bedeutet, dass der Skalierungsfaktor eines Systems pro hinzugefügter Ressourcen-Einheit gleich bleibt.

Sub-Lineare Skalierbarkeit steht im Gegensatz dazu für die Abnahme des Skalierungsfaktors beim Hinzufügen von Ressourcen.

Negative Skalierbarkeit wird erreicht, wenn sich die Leistung durch das Hinzufügen von Ressourcen/Rechnern sogar verschlechtert. Mit diesem Problem hat man zu kämpfen, wenn der Verwaltungsaufwand, welcher durch den zusätzlichen Rechner entsteht, größer ist als der dadurch erreichte Leistungszuwachs.

Datei:Graph Skalierbarkeit.jpg

Amdahl's Gesetz Bearbeiten

Das Amdahlsche Gesetz (benannt 1967 nach Gene Amdahl) ist ein Modell in der Informatik über die Beschleunigung von Programmen durch parallele Ausführung. Nach Amdahl wird der Geschwindigkeitszuwachs vor allem durch den sequentiellen Anteil des Problems beschränkt, da sich dessen Ausführungszeit durch Parallelisierung nicht verringern lässt.

Amdahls Gesetz ist eines der pessimistischsten zur Abschätzung des theoretischen SpeedUps, da es einige positive Faktoren nicht berücksichtigt. Nach Amdahl ist die größtmögliche Beschleunigung linear, also durch die 10-fache Anzahl von Kernen ist maximal die 10-fache Rechenleistung möglich. Jedoch ist in jeder CPU auch Cache integriert, so dass sich auch die Menge an schnellem Speicher verzehnfacht. Im günstigsten Fall ist es so möglich, die gesamte Problemgröße im Cache anstatt im langsamen Hauptspeicher zu halten, was einen super-linearen SpeedUp ermöglicht, also Beschleunigung, die über die zusätzliche, reine Rechenleistung hinausgeht. Allerdings könnte dies darauf zurückzuführen sein, dass der Vergleich aus dem Grund fehlerhaft ist, dass der integrierte Cache als Teil des Prozessormoduls betrachtet wird. Ein Vergleich ohne Berücksichtigung der Cache-Größe würde nicht zu dem benannten super-linearen SpeedUp führen. Amdahls Betrachtung für den maximalen Speedup bleibt jedoch in beiden Fällen gültig.

Weiterhin geht Amdahl in seiner Rechnung davon aus, dass die Problemgröße unverändert bleibt; das Ziel ist also, ein Problem in möglichst kurzer Zeit zu berechnen. Für den Fall, in der gleichen Zeit ein größeres Problem zu berechnen, ergeben sich günstigere Voraussetzungen, da der parallele Anteil je nach Problem dann sehr groß werden kann. Je länger eine Berechnung dauert, desto weniger fällt die Zeit für die Initialisierung und abschließende Synchronisierung ins Gewicht.

Beispiel 1: Angenommen 100% der Operationen sind parallelisierbar. Die Leistung eines 2-Prozessor-Systems steigt folglich maximal auf 200%. Anders ausgedrückt: wir sind in 50% der Zeit fertig.

Beispiel 2: Angenommen nur 50% der Operationen sind parallelisierbar. Dann steigt die Leistung eines 4-Prozessor-Systems auf höchstens 160%. Anders ausgedrückt: wir sind in 62,5% der Zeit fertig.

Erklärung: Nachdem 50% der Operationen nicht parallelisierbar sind, benötigt 1 Prozessor 50% + 12,5% der ursprünglichen Zeit und die restlichen 3 jeweils 12,5% der ursprünglichen Zeit. Siehe nachfolgende Abbildung, wobei P der parallelisierbare Anteil ist.

-->Abbildung: Datei:Beispiel amdahls law.gif

Gustafsons Gesetz Bearbeiten

Gustafsons Gesetz basiert auf dem Gesetz von Amdahl, das, ausgehend von einer festen Problemgröße, versucht eine zu bewältigende Aufgabe durch Parallelisierung mit   Prozessoren in kürzerer Zeit zu lösen. Es geht dabei davon aus, dass das bestmögliche Ergebnis eine lineare Verbesserung der benötigten Zeit (also  ) sei. Verwendet man doppelt soviel Prozessoren, benötige man bestenfalls die halbe Zeit.

Gustafson veränderte das Gesetz so, dass es ein festes Zeitfenster verwendet, in dem die Problemgröße mit der Anzahl der Prozessoren wächst. Verwendet man doppelt soviel Prozessoren, kann man bestenfalls eine doppelt so große Aufgabe lösen. Obwohl sie auf den ersten Blick gleich erscheinen, unterscheiden sich die Aussagen signifikant.

Ein Programm kann nie vollständig parallel ausgeführt werden, da einige Teile, wie Prozessinitialisierung oder Speicherallokation nur einmalig auf einem Prozessor ablaufen oder der Ablauf von bestimmten Ergebnissen abhängig ist. Daher zerlegt man den Programmlauf in Abschnitte, die entweder vollständig sequentiell oder vollständig parallel ablaufen und fasst sie zu jeweils einer Gruppe zusammen. Sei   der Anteil der Laufzeit der parallelen Teilstücke eines Programms, dann ist ( ) der sequentielle Anteil und die Gesamtlaufzeit ergibt sich bei Ausführung auf einem Kern aus der Summe:

 

Gemäß dieser Formel werden beide Teile auf einem seriellen Rechner hintereinander ausgeführt, die Zeiten addieren sich auf. Vernachlässigt man den Overhead für Kommunikation, Synchronisierung und dergleichen, so lässt sich der parallele Anteil auf   Prozessoren gleichzeitig ausführen. Für den Beschleunigungsfaktor (SpeedUp)   gilt damit

 

Der entscheidende Unterschied zu Amdahl ist, dass der parallele Anteil mit der Anzahl der Prozessoren wächst. Der sequentielle Part wirkt hier nicht beschränkend, da er mit zunehmendem   unbedeutender wird. Geht   gegen unendlich, so wächst der SpeedUp linear mit der Anzahl der Prozessoren  .

Schichtenmodell Bearbeiten

Bei einem gut skalierenden System ist ein entscheidender Faktor jener, dass jede Schicht dieser Architektur gut skaliert.

Eine Schichtenarchitektur oder Schichtenmodell ist ein häufig angewandtes Strukturierungsprinzip für die Architektur von Softwaresystemen. Dabei werden einzelne Aspekte des Softwaresystems konzeptionell einer Schicht (engl. tier oder layer) zugeordnet. Die erlaubten Abhängigkeitsbeziehungen zwischen den Aspekten werden bei einer Schichtenarchitektur dahin gehend eingeschränkt, dass Aspekte einer „höheren“ Schicht nur solche „tieferer“ Schichten verwenden dürfen. Ein System mit Schichtenarchitektur bezeichnet man auch als mehrschichtig.

Schichtenarchitekturen nach Anzahl Schichten Bearbeiten

Zwei-Schichten-Architektur Bearbeiten

 
Beispiel einer 2-Schichten-Architektur

Die zweischichtige Architektur (englisch two tier architecture) besteht aus zwei Schichten. Da nur die höhere auf die niedrigere Schicht zugreifen darf, ist die niedrigere Schicht ein Dienstanbieter (engl. Server) der höheren. Man spricht daher auch oft von einer Client-Server-Architektur.

Client-Server-Architekturen müssen nicht notwendigerweise mittels unterschiedlicher Rechner realisiert sein, vielmehr kann der Client auch als ein Software-Modul verstanden werden, das auf ein zweites Software-Modul auf demselben Rechner, meist innerhalb derselben Anwendung zugreift. Das in der Abbildung gegebene Beispiel greift jedoch auf eine rechnerseitige Client-Server-Architektur zurück.

Bei Architekturen wie in der Abbildung gegeben wird die Rechenkapazität weitestgehend auf die Client-Rechner ausgelagert, um den Server zu entlasten. Traditionell kommt ein Fat-Client und ein Thin-Server zum Einsatz. Auf dem Server läuft eine Datenbankanwendung. Die Clients übernehmen dabei die Logik und die Darstellung der Benutzerschnittstelle.

Drei-Schichten-Architektur Bearbeiten

 
Beispiel einer 3-Schichten-Architektur

Die dreischichtige Architektur (englisch three tier architecture) ist eine Architektur, die softwareseitig drei Schichten hat. Im Gegensatz zur zweischichtigen Architektur existiert bei der dreischichtigen Architektur noch eine zusätzliche Schicht, oftmals die Logikschicht, welche die Datenverarbeitung vornimmt.

Eine typische Drei-Schichten-Architektur besteht aus den folgenden Schichten:

  • Präsentationsschicht (client tier) – Diese, auch Front-End bezeichnet, ist für die Repräsentation der Daten, Benutzereingaben und die Benutzerschnittstelle verantwortlich.
  • Logikschicht (application-server tier, Businessschicht, Middle Tier oder Enterprise Tier) – Sie beinhaltet alle Verarbeitungsmechanismen. Hier ist die Anwendungslogik vereint.
  • Datenhaltungsschicht (data-server tier, back end) – Sie enthält die Datenbank und ist verantwortlich für das Speichern und Laden von Daten.

Drei-Schichten-Architekturen bei verteilten Systemen Bearbeiten

 

Mehrschichtige Systemarchitekturen wie die dreischichtige Architektur sind gut skalierbar, da die einzelnen Schichten logisch voneinander getrennt sind. So kann z. B. bei verteilten Systemarchitekturen die Datenschicht auf einem zentralen Datenbank-Server laufen, die Logikschicht auf Workgroup-Servern, und die Präsentationsschicht befindet sich auf der jeweiligen Workstation des Benutzers. Ein Beispiel für eine verteilte Drei-Schichten-Architektur ist Citrix: Interaktion: Client; Funktion: Citrix Server; Daten: Datenbankserver.

Wie die Grafik zeigt, gibt es zwischen Client und Server verschiedene Möglichkeiten zur Verteilung der Schichten. Grundsätzlich gilt: Je höher (näher an der Präsentationsschicht) die Schicht ist, desto eher wird sie von einem Client bearbeitet. Je tiefer (näher an der Datenschicht) die Schicht ist, desto eher ist sie Aufgabe eines Servers.

Klassische Schichten innerhalb einer mehrschichtigen Architektur Bearbeiten

Präsentationsschicht Bearbeiten

 
Erweiterung einer Drei-Schichten-Architektur um Präsentations-Schicht

Die Präsentationsschicht (engl. client layer oder presentation layer) ist für die Darstellung und Entgegennahme von der Software bearbeiteten Daten, sowie der von der Software bereitgestellten Funktionen verantwortlich.

Bei verteilten Systemen existieren für die Darstellung der Inhalte zwei Alternativen:

Logikschicht Bearbeiten

Die Logikschicht (auch Verarbeitungsschicht, Anwendungslogikschicht, Domänenschicht, application layer oder middle tier) realisiert das eigentliche Geschäftsmodell, indem die am Geschäftsmodell beteiligten Geschäftsobjekte mit der zugehörigen Logik implementiert werden.

Datenhaltungsschicht Bearbeiten

 
Erweiterung Daten-Integrations-Schicht

Die Datenhaltungsschicht kapselt den Zugriff auf persistente Daten und die dabei verwendeten Techniken.

Für die persistente Speicherung werden häufig Datenbanken eingesetzt, bei anderen Systemen können aber auch normale Dateien verwendet werden.

Beim Einsatz von Datenbanken werden für den Datenaustausch mit der Datenhaltungsschicht Datenbankschnittstellen sowie alternativ der direkte Zugriff auf das DBMS (Datenbank Management System) verwendet (z. B. bei PHP). Bei Verwendung von objektorientierter Programmierung im Zusammenspiel mit einem relationalen DBMS wird in der Datenzugriffsschicht eine objektrelationale Abbildung (object-relational mapping, ORM) benötigt, die oft durch den Einsatz eines ORM-Frameworks umgesetzt wird.

Während die Präsentationsschicht relativ einfach horizontal skaliert werden kann, ist bei der Logikschicht dafür eine speziell dafür ausgelegte Implementierung des Codes erforderlich. Dabei ist zu berücksichtigen, dass ein möglichst großer Anteil der Logik parallelisiert werden kann (siehe Amdahls Gesetz und Gustafsons Gesetz weiter oben). Am interessantesten ist jedoch die horizontale Skalierung der Datenhaltungsschicht, weshalb diesem Thema ein eigener Abschnitt (siehe horizontales Skalieren der Datenhaltungsschicht weiter unten) gewidmet ist.

praktische Methoden zur Verbesserung der Skalierbarkeit von Webseiten Bearbeiten

Verbesserung der Skalierbarkeit von Webseiten kann durch Steigerung der Performance erzielt werden, da ein Server dadurch mehr Clients in der gleichen Zeit bedienen kann.

Martin L. Abbott und Michael T. Fisher haben 50 Regeln aufgestellt, die es in Bezug auf Skalierbarkeit zu beachten gilt[3]. Für Webseiten sind dabei unter anderem folgende Regeln relevant:

Reduzieren von DNS-Lookups und Anzahl von Objekten Bearbeiten

Beim Betrachten des Ladens einer Seite in einem beliebigen Browser mit einem Debugging-Tool (z.B. Firebug) fällt auf, dass ähnliche große Elemente unterschiedliche lange Ladezeiten beanspruchen. Bei genauerer Betrachtung erkennt man, dass einige dieser Elemente einen zusätzlich DNS-Lookup benötigen. Dieser Vorgang der Adressauflösung kann durch Caching auf unterschiedlichen Ebenen (z.B. Browser, Betriebssystem, Internet Provider etc.) beschleunigt werden. Um die Anzahl der Lookups zu reduzieren, könnte man nun alle Javascript- und CSS-Dateien zu jeweils einer zusammenfassen und man könnte alle Bilder auf ein großes zusammenfügen und mittels CSS nur den gewünschten Bildausschnitt anzeigen. Allgemein kann man folgende Regel dazu aufstellen: Jede weniger DNS-Lookups beim Laden einer Seite erforderlich sind, desto besser ist die Performance. Die folgende Grafik veranschaulicht wie teuer der DNS-Lookup und der Verbindungsaufbau verhältnismäßig sind.

--> Abbildung: Datei:Object download time.gif


Moderne Browser können jedoch mehrere Verbindungen gleichzeitig zu einem Server offen halten um mehrere Objekte parallel herunterzuladen. Laut HTTP/1.1 RFC[4] sollte das Maximum an gleichzeitigen Verbindungen je Server im Browser auf 2 limitiert werden. Einige Browser ignorieren diese Richtlinie jedoch und verwenden ein Maximum von 6 gleichzeitigen Verbindungen und mehr. Reduziert man auf einer Webseite nun jedoch alle Javascript- und CSS-Dateien, sowie alle Bilder lediglich auf jeweils eine Datei, so entlastet man zwar die anbietenden Server, hebelt jedoch gleichzeitig diesen Mechanismus der parallelen Verbindungen des Browser aus.

Idealerweise nutzt man diese Parallelisierung im Browser zur Gänze aus und hat gleichzeitig möglichst wenige DNS-Lookups. Um das zu erreichen verteilt man eine Webseite am besten auf mehrere Subdomains (z.B. ruft man Bilder von einer Subdomain auf, während man Videos von einer anderen lädt). Durch diese Vorgehensweise lässt sehr rasch eine beachtliche Performance-Steigerung erzielen. Leider gibt es jedoch keine allgemeine Antwort darauf, wie viele Subdomains man verwenden sollte um die bestmögliche Leistung zu erzielen. Einfache Performance-Tests der zu optimierenden Seite sollten darüber jedoch rasch Aufschluss bieten.

horizontales Skalieren der Datenhaltungsschicht Bearbeiten

Skalierung hinsichtlich Datenbankzugriffe Bearbeiten

Der am schwierigsten zu skalierende Teil eines Systems ist meistens die Datenbank bzw. die Datenhaltungsschicht (s. o.). Der Ursprung dieses Problem kann bis zum Paper "A Relational Model of Data for Large Shared Data Banks"[5] von Edgar F. Codd zurückverfolgt werden, welches das Konzept eines Relational Database Management System (RDBMS) vorstellt.

Eine Methode um Datenbanken zu skalieren ist, sich den Fakt, dass die meisten Anwendungen und Datenbanken wesentlich mehr Lese- als Schreibzugriffe aufweisen, zu Nutze zu machen. Ein durchaus realistisches Szenario, das in dem Buch von Martin L. Abbott und Michael T. Fisher beschrieben wird, ist eine Buchreservierungsplattform welche ein Verhältnis zwischen Lese- und Schreibzugriffen von 400:1 aufweist. Diese Art von Systemen können relativ einfach skaliert werden, indem mehrere read-only Duplikate dieser Daten angefertigt werden.

Es gibt mehrere Wege um die Kopien dieser Daten zu verteilen abhängig davon, wie aktuell die Daten der Duplikate wirklich sein müssen. Grundsätzlich sollte es kein Problem sein, dass diese Daten lediglich alle 3, 30, oder 90 Sekunden synchronisiert werden. Bei dem Szenario der Buchplattform gibt es 100 000 Bücher und 10% davon werden täglich reserviert. Angenommen die Reservierungen sind gleichmäßig über den gesamten Tag verteilt, so findet ca. eine Resevierung pro Sekunde (0,86 Sek.) statt. Die Wahrscheinlichkeit dass zum Zeitpunkt (innerhalb 90 Sek.) einer Reservierung ein anderer Kunde das gleiche Buch reservieren möchte, beträgt 0,104%. Natürlich kann und wird dieser Fall irgendwann eintreffen, doch diesem Problem kann ganz einfach durch eine abschließende, erneute Überprüfung der Datenbank entgegentreten werden.

Eine Möglichkeit um diese Methode umzusetzen ist jene, die Daten, z.B. mit einem Key-Value-Store (z.B. Redis), zu cachen. Der Cache muss erst nach Ablauf seiner Gültigkeit erneuert werden und entlastet damit die Datenbank enorm. Der einfachste Weg diesen Cache zu implementieren, ist ihn in einer bereits bestehenden Schicht (z.B. der Logikschicht) zu installieren. Für eine bessere Performance und Skalierbarkeit verwendet man dafür jedoch eine eigene Schicht, bzw. eigene Server, zwischen der Logikschicht und der Datenhaltungsschicht.

Der nächste Schritt ist nun die Datenbank zu replizieren. Die meisten bekannten Datenbanksysteme verfügen bereits über eine solche Funktion. MySQL bewerkstelligt dies mit dem master-slave-Prinzip, wobei die master-Datenbank die eigentliche Datenbank mit Schreibrechten ist und die slave-Datenbanken die duplizierten read-only Kopien sind. Die master-Datenbank zeichnet sämtliche updates, inserts, deletes, etc. im sogenannten Binary-Log auf und die slaves reproduzieren diese. Diese slaves steckt man nun hinter einen Load Balancer (s. u.) um die Last entsprechend zu verteilen.

Diese Art von Skalierung lässt die Anzahl der Transaktionen relativ einfach skalieren. Je mehr Duplikate der Datenbank verwendet werden, desto mehr Transaktionen können auch parallel bewältigt werden. In anderen Worten bedeutet das, dass nun beliebig viele User (natürlich abhängig von der Anzahl der Server) gleichzeitig auf unsere Datenbank zugreifen können. Leider hilft uns diese Methode nicht dabei, auch die Daten an sich zu skalieren. Um nun auch beliebig viele Daten in der Datenbank speichern zu können, ist ein weiterer Schritt nötig. Dieses Problem wird im nächsten Punkt behandelt.

Skalierung hinsichtlich Datenbankeinträge - Denormalisierung Bearbeiten

Was man hiermit erreichen möchte, ist eine Datenbank auf mehrere Rechner aufzuteilen und dessen Kapazität beliebig durch weitere Rechner zu erweitern. Dazu muss die Datenbank zu einem gewissen Grad denormalisiert werden. Unter Denormalisierung versteht man die bewusste Rücknahme einer Normalisierung zum Zweck der Verbesserung des Laufzeitverhaltens einer Datenbankanwendung.

Im Zuge der Denormalisierung muss die Datenbank fragmentiert werden.

Fragmentierung Bearbeiten

Man unterscheidet horizontale und vertikale Fragmentierung.

Bei der Horizontalen Fragmentierung (Eng. sharding) wird die Gesamtheit aller Datensätze einer Relation auf mehrere Tabellen aufgeteilt. Wenn diese Tabellen auf demselben Server liegen, dann handelt es sich meistens um Partitionierung. Die einzelnen Tabellen können aber auch auf unterschiedlichen Servern liegen. So können z.B. die Daten für die Geschäfte in den USA auf einem Server in den USA gespeichert werden und die Daten für die Geschäfte mit Europa liegen auf einem Server in Deutschland. Diese Aufteilung wird auch als Regionalisierung bezeichnet.

Horizontale Fragmentierung schafft keine Redundanz der gespeicherten Daten, sondern der Strukturen. Wenn eine Relation geändert werden muss, dann muss nicht nur eine Tabelle geändert werden, sondern es müssen alle Tabellen geändert werden, über die die Daten aus der betreffenden Relation verteilt sind. Hier besteht die Gefahr von Anomalien in den Datenstrukturen.

Bei der Vertikalen Fragmentierung werden die abhängigen Attribute (nicht-Schlüssel-Attribute) einer Tabelle in zwei oder mehrere Gruppen aufgeteilt. Aus jeder Gruppe wird eine eigene Tabelle, die noch um alle Schlüssel-Attribute der Ursprungstabelle ergänzt werden. Das kann dann sinnvoll sein, wenn die Attribute einer Relation Datensätze mit einer sehr großen Satzlänge ergeben. Wenn zusätzlich noch die Zugriffe meistens nur einige wenige Attribute betreffen, dann kann man die wenigen häufig zugegriffenen Attribute in eine Gruppe zusammenfassen und den Rest in eine zweite Gruppe zusammenfassen. Die häufig auszuführenden Zugriffe werden dadurch schneller, weil eine geringere Menge an Daten von der Festplatte gelesen werden muss. Die selten auszuführenden Zugriffe auf die restlichen Attribute werden dadurch nicht schneller, aber auch nicht langsamer.

Ab welcher Satzlänge eine Aufspaltung in mehrere kleinere Tabellen sinnvoll ist, hängt auch von dem Datenbanksystem ab. Viele Datenbanksysteme speichern die Daten in Form von Blöcken mit einer Größe von 4KiB, 8KiB oder 16KiB ab. Wenn die durchschnittliche Satzlänge wenig größer als 50 % eines Datenblocks ist, dann bleibt viel Speicherplatz ungenutzt. Wenn die durchschnittliche Satzlänge größer als die verwendete Blockgröße ist, dann werden die Datenzugriffe aufwändiger. Wenn BLOBs zusammen mit anderen Attributen in einer Relation vorkommen, ist vertikale Fragmentierung fast immer von Vorteil.

Partitionierung Bearbeiten

Partitionierung ist ein Spezialfall der horizontalen Fragmentierung.

Große Datenbestände lassen sich leichter administrieren, wenn die Daten einer Relation in mehrere kleine Teile (=Partitionen) aufgeteilt und diese separat gespeichert werden. Wenn eine Partition einer Tabelle gerade aktualisiert wird, dann können andere Partitionen der Tabelle zur selben Zeit reorganisiert werden. Wenn in einer Partition ein Fehler entdeckt wird, dann kann diese einzelne Partition aus einer Datensicherung wiederhergestellt werden, während Programme auf die anderen Partitionen weiter zugreifen können. Die meisten etablierten Datenbankhersteller bieten Partitionierung an, siehe z.B. Partitionierung bei DB2 und Partitionierung bei MySQL.

Die meisten Datenbanksysteme bieten die Möglichkeit, entweder einzelne Partitionen anzusprechen oder alle Partitionen unter einem einheitlichen Tabellennamen anzusprechen.

Durch Partitionierung können die Datenzugriffe beschleunigt werden. Der wesentliche Vorteil ist jedoch die leichtere Administrierbarkeit der gesamten Tabelle.

Lastverteilung Bearbeiten

Bei horizontal skalierten Systemen spielt die Lastverteilung (engl. Load Balancing) eine zentrale Rolle.

In der Computertechnik werden umfangreiche Berechnungen oder große Mengen von Anfragen mittels Lastverteilung auf mehrere parallel arbeitende Systeme verteilt. Dies kann sehr unterschiedliche Ausprägungen haben. Eine einfache Lastverteilung findet zum Beispiel auf Rechnern mit mehreren Prozessoren statt. Jeder Prozess kann auf einem eigenen Prozessor ausgeführt werden. Die Art der Verteilung der Prozesse auf Prozessoren kann dabei einen großen Einfluss auf die Gesamtperformance des Systems haben, da z. B. der Cache-Inhalt lokal für jeden Prozessor ist.

Ein anderes Verfahren findet man in Computerclustern. Hierbei bilden mehrere Rechner einen Verbund, der sich nach außen meistens wie ein einzelnes System verhält. Dies wird mit Serverlastverteilungsverfahren realisiert. Einige mögliche Verfahren sind das Vorschalten eines Computers, der die Anfragen aufteilt, oder die Verwendung von DNS mit dem Round-Robin-Verfahren.

Lastverteilung wird ebenfalls bei Daten-/Sprachleitungen verwendet, um den Verkehrsfluss auf parallel geführte Leitungen zu verteilen. In der Praxis treten jedoch häufig Probleme dabei auf, den Daten-/Sprachverkehr gleichmäßig auf beide Leitungen zu verteilen. Es wird daher meist die Lösung implementiert, dass eine Leitung als Hin- und die zweite Leitung als Rückkanal Verwendung findet.

Lastverteilung findet auch bei großen Server-Farmen statt, die z. B. der Beantwortung von HTTP-Anfragen dienen. Dort sind Systeme vorgeschaltet (Frontend Server), die nach festgelegten Kriterien die einzelnen Anfragen auf die Backend Server verteilen. Dabei können zusätzliche Informationen aus dem HTTP-Request verwendet werden, um alle zu einer Session mit einem Benutzer gehörenden Pakete an den gleichen Server zu schicken. Dies ist auch bei der Nutzung von SSL zur Verschlüsselung der Kommunikation wichtig, damit nicht für jede Anfrage ein neuer SSL-Handshake durchgeführt werden muss.

Eine gute Umsetzung einer Lastverteilung erfordert immer Informationen darüber, wie die Auslastung der Zielsysteme aussieht.

Unter dem Begriff load balancing wird im weitesten Sinne auch ein Mechanismus zur Ausfallsicherheit verstanden: durch den Aufbau eines Clusters (siehe: Computercluster) und der Verteilung der Anfragen auf einzelne Systeme, erreicht man eine Erhöhung der Ausfallsicherheit, sofern der Ausfall eines Systems erkannt und die Anfragen automatisch an ein anderes System abgegeben werden (siehe auch: Hochverfügbarkeit bzw. High-Availability, „HA“).

Einzelnachweise Bearbeiten

  1. See for instance, Mark D. Hill, 'What is scalability?' in ACM SIGARCH Computer Architecture News, December 1990, Volume 18 Issue 4, pages 18–21, (ISSN 0163-5964) and Leticia Duboc, David S. Rosenblum, Tony Wicks, 'Doctoral symposium: presentations: A framework for modelling and analysis of software systems scalability' in Proceeding of the 28th international conference on Software engineering ICSE '06, May 2006. ISBN 1-59593-375-1, pages 949–952
  2. Michael, M., J.E. Moreira, D. Shiloach, R.W. Wisniewski: Scale-up x Scale-out: A Case Study using Nutch/Lucene. In: Parallel and Distributed Processing Symposium, 2007. IPDPS 2007. IEEE International, 26. März 2007, abgerufen am 23. Mai 2012.
  3. Abbott L. M., M. T. Fisher 2011. Scalability Rules: 50 principles for scaling Web sites, Indiana: Addison-Wesley, ISBN 978-0-321-75388-5, S.12-34
  4. R. Fielding, J. Gettys, J. Mogul, H. Frystyk, L. Masinter, P. Leach, and T. Berners-Lee, Network Working Group Request for Comments 2616, Hypertext Transfer Protocol-HTTP/1.1, Juni 1999, http://www.ietf.org/rfc/rfc2616.txt
  5. Edgar F. Codd: A Relational Model of Data for Large Shared Data Banks. In: Communications of the ACM. ACM Press, 13. Juni 1970, ISSN 0001-0782, S. 377–387.

Siehe auch Bearbeiten

[[Kategorie:Softwaretechnik]]