My-Hammer, das Fernsehen und die Serverlast: Teil 2

Dies ist Teil 2 der Artikelserie zum Thema Webseiten-Skalierung. Die anderen Teile:

Teil 1: Allgemeine Überlegungen
Teil 2: Datenbankoptimierung
Teil 2.1: Praxistipps Datenbank
Teil 3: Caching
Teil 4: Zukünftige Optimierungen (folgt)

Hinweis: Thematisch durchaus verwandt berichtet Tom Bachem über die Systemarchitektur von sevenload.

Welche Massnahmen kann man nun konkret ergreifen, um sich auf einen TV Beitrag über die eigene Webseite vorzubereiten? Ich versuche so allgemein wie möglich zu bleiben, aber da es um konkrete Ratschläge gehen soll und ich holprige Umschreibungen vermeiden möchte, wird das Vokabular ab jetzt etwas LAMP-lastig; bitte entsprechend auf die eigene Technik ummünzen.

Massnahme 1: Datenbankoptimierung

Wurde ja schon erwähnt: die Indizes. Ich verrate wahrscheinlich nicht einmal DB Anfängern etwas neues, wenn ich betone, dass dies essentiell ist. Wenn man die Indizes nicht im Griff hat, braucht man sich die anderen Punkte noch gar nicht anschauen. Deshalb: Ins Slow-Log gucken. Vor allem: Immer wieder. Einen Status Quo gibt es nicht! Immer wieder EXPLAIN bemühen, vom stumpf auf die Strukturen in phpMyAdmin gucken findet man die Performancefresser nicht.

Es gibt diese missverständliche Formel “Braucht man Geschwindigkeit, nimmt man MyISAM, braucht man Sicherheit, InnoDB”. InnoDB ist nicht nur einen Blick wert, wenn man Transaktionssicherheit braucht. Im Gegensatz zu MyISAM lockt InnoDB bei schreibenden Queries immer nur die betreffenden Zeilen, MyISAM dagegen grundsätzlich die gesamte Tabelle. InnoDB hat zwar aufgrund der größeren Komplexität etwas mehr “Grundoverhead”, aber das intelligentere Locking kann immens wertvoll sein in bestimmten Szenarien und das mehr als wettmachen. Wenn man eine Tabelle hat die man hinsichtlich Struktur und Indices schon perfekt durchoptimiert hat (genau das aber wiederum erstmal sicherstellen!), und trotzdem tauchen Queries auf diese Tabelle immer noch im Slow Log auf, dann sollte man prüfen, ob diese Queries vielleicht immer auf einen Lock warten. In diesem Fall InnoDB auf jeden Fall eine Chance geben. Das hat bei uns konkret bei den Session und Cachetabellen (dazu später mehr) enorm viel gebracht, weil dort die Lese- und Schreibzugriffe ein ausgewogenes Verhältnis haben.

Ein Aspekt, der wenig berücksichtigt wird, ist die Größe der Felder, auf die man Indices setzt. Es kann sich lohnen, hier sparsam zu sein, denn ein kleinerer Spaltentyp bedeutet auch weniger Speicherplatzverbrauch für den Index auf diese Spalte, und das kann im Zweifel nur gut (= schneller) sein. Man ist halt geneigt, seine Primary IDs immer als INT anzulegen. Aber nehmen wir mal den Klassiker Benutzertabelle: Wird man wirklich in nächster Zeit 4 Milliarden User haben? Das dürfte selbst bei eBay noch ein bisschen dauern. Erstmal tut es also auch ein MEDIUMINT, setzt man diesen UNSIGNED, ist das Limit bei 16 Millionen. Hat man soviele User, bewegt man sich wohl eh in völlig anderen Dimensionen.
Zumal das Umwandeln einer Spalte in einen Typ mit größerem Wertbereich (also z.B. von MEDIUMINT nach INT) unproblematisch ist. Wichtig ist allerdings auch, dass man sämtliche Felder, die einen Fremdschlüssel auf ein MEDIUMINT Feld darstellen, ebenfalls als MEDIUMINT anlegt, sonst hat man bei Joins nichts gewonnen.

Was bei der Skalierung von MySQL immer enorm hilft ist Replikation. Dazu wurde schon so viel geschrieben, dass ich mir die Wiederholung spare, nur dies: Wir fahren bisher sehr gut damit, das Balancing der Nur-Lese Zugriffe direkt in unserer Applikation zu regeln, und nicht über einen eigenen Software- oder Hardware-Loadbalancer. Da bei fast jedem Seitenaufruf der Master sowieso früher oder später konnektiert werden muss, kann man diese Verbindung auch nutzen, um MASTER STATUS und SLAVE STATUS zu vergleichen, um so ein Fallback auf den Master zu realisieren, falls alle Slaves einmal mehr als 0 Sekunden hinter dem Master zurückhängen. Was sich übrigens ziemlich gut vermeiden lässt, wenn man Master und Slaves per Gigabit statt Fast Ethernet anbindet.

Ein oft nicht wahrgenommener Vorteil von Replikation: Man kann einen Slave für’s Backup bereitstellen, auf dem man die Datenbank stoppen und auf Dateisystemebene wegkopieren kann (oder man hält nur den Slave Thread an und macht einen Dump), so dass man einen sauberen Snapshot der Datenbank hat, ohne das Gesamtsystem anhalten zu müssen.

Ein weiterer wichtiger Hebel für die Skalierung ist es, für spezielle Aufgaben jeweils eigene DB Server bereitzustellen, z.B. ein oder mehrere Maschinen nur für die Sessiontabellen, nur für Tabellen mit Cache-Inhalten, nur für Logtabellen; prinzipiell kann jede Tabelle, die nicht in Form von Joins oder Subselects zusammen mit anderen Tabellen gleichzeitig abgefragt werden muss, auch getrennt von den anderen Tabellen auf einem eigenen Server liegen. Darüber hinaus macht die Trennung von sehr verschiedenen Tabellen wie Session- und Logtabellen alleine deshalb schon Sinn, weil man dann die Datenbanksoftware für diese speziellen Aufgaben optimieren kann.

My-Hammer, das Fernsehen und die Serverlast: Teil 1

Dies ist Teil 1 der Artikelserie zum Thema Webseiten-Skalierung. Die anderen Teile:

Teil 1: Allgemeine Überlegungen
Teil 2: Datenbankoptimierung
Teil 2.1: Praxistipps Datenbank
Teil 3: Caching
Teil 4: Zukünftige Optimierungen (folgt)

Vergangenen Donnerstag zeigte das ProSieben Magazin Galileo einen ca. 10-minütigen Beitrag über My-Hammer (kurze Infos zur Sendung hier). Vom Ansatz her ging es um “Branchenbuch vs. My-Hammer”, aber für die Betrachtung hier ist das gar nicht so sehr von Interesse - es ist noch nichtmal von Interesse, ob so ein Beitrag positiv oder negativ für uns ist (in dem Fall war’s wie fast immer positiv) - sobald das Magazin, in dem über uns berichtet wird, genug Reichweite hat, schießen die Zugriffe in die Höhe. Die wichtigste Erkenntnis, die wir immer wieder machen: zumindest bei den Privaten scheinen die Zuschauer sprichwörtlich mit dem Laptop auf den Knien vorm Fernseher zu sitzen. Die Zugriffe kommen extrem schnell und gebündelt (beim Galileo-Beitrag war aber interessant, dass die Zugriffe wieder auf einen Schlag kamen, aber erst in dem Moment, in dem der Beitrag vorbei war).

Genau dieses plötzliche Auftreten so vieler Zugriffe ist natürlich die Herausforderung - dieselbe Anzahl User auf nur 15 Minuten verteilt wären kein Problem, aber TV sorgt dafür, dass das meiste innerhalb der ersten 5 Minuten passiert. Und es ist wirtschaftlich natürlich ziemlich unvernünftig, die für diese 5 Minuten benötigte Rechenpower anzuschaffen, nur damit sie die anderen 525.595 Minuten im Jahr vor sich hindümpelt.

Trotzdem kann man eine Webseite auch auf solche Extremsituationen vorbereiten - My-Hammer hat am Donnerstag perfekt standgehalten, lediglich eine leichte Verzögerung in den Ladezeiten war während der kritischen Phase spürbar.

Um kurz die Dimensionen klarzumachen, erstmal eine Grafik, welche den ein- und ausgehenden IP Traffic für unser Netzwerk anzeigt. Man sieht sehr deutlich den Sprung auf das gut 2,5-fache des normalen Werts. Der Faktor selbst klingt vielleicht erstmal nicht so dramatisch, aber wie erwähnt geht es nicht um die Masse an sich, sondern das extrem gebündelte Auftreten dieser Masse an Zugriffen:

IP-Traffic My-Hammer

Ich behaupte mal, man erkennt recht gut, wann die Sendung lief…

Also, wie kann man die Serversysteme auf so etwas vorbereiten? Klar: mehr Server kaufen. Das ist durchaus ein Aspekt, aber nicht das Allheilmittel. Vor allen Dingen kann das sehr ineffektiv und unwirtschaftlich sein. Angenommen, man hat Server A mit einer gewissen Leistungsfähigkeit. Nun kann man sich Server B mit doppelt so schnellem Prozessor, doppeltem Arbeitsspeicher und doppelt so schnellen Festplatten kaufen. Dann hat man schon Unmengen von Geld ausgegeben, und hat gerade mal eine Steigerung der Leistungsfähigkeit von 100% (mal davon abgesehen, dass die Rechnung “doppelt so schnelle Hardware, doppelt so viel Leistung” in der Praxis auch nicht wirklich hinhaut). Dagegen kann ein einziger geschickt gesetzter Index in der Datenbank manchmal 1000% bessere Performance bringen, ohne dass man etwas an der Hardware tut.

Wenn man den Anschaffungspreis neuer Hardware mal auf den Stundenlohn eines Entwicklers umrechnet, wird man schnell zu dem Schluss kommen, dass es sich auch finanziell durchaus rechnen kann, diesen einige Tage lang auf die Datenbank anzusetzen um zu schauen, ob nicht doch irgendwo ein wichtiger Index vergessen wurde oder einige Tabellenstrukturen besser ganz anders aufgebaut sein sollten.

Das sind nur ein paar grundsätzliche Überlegungen. Spürbaren Erfolg wird man nur haben, wenn man ein ganzes Bündel an Massnahmen ergreift und vor allem immer das Gesamtsystem vom Code über die Datenbank bis hin zu den Servern und dem Netzwerk im Überblick hat. Die vielleicht wichtigste Faustregel, wenn man über Performanceoptimierung von Webseiten spricht, scheint mir daher zu sein: Coder und Admins an einen Tisch! Es hilft nichts, wenn die Entwickler meinen, die Geschwindigkeit des Systems sei doch schliesslich Sache des Admins. Umgekehrt ist es extrem hilfreich, wenn die Programmierer auch einen gewissen Sysadmin-Background haben, und die Admins umgekehrt auch Programmiererfahrung haben; was bei uns glücklicherweise sogar sehr ausgeprägt der Fall ist.

Die weiteren Teile befassen sich mit den konkreten Massnahmen, die man ergreifen kann um sich auf einen TV Beitrag vorzubereiten.

Using apt on Etch connecting to an apt-proxy on Sarge causes trouble with .diff files

openlogo-nd-50.pngSay you have an installation of apt-proxy running on a Debian Sarge machine to serve files for apt on your other machines, then you will receive errors like this when issuing an apt-get update on an Etch machine: Error reading from server. Remote end closed connection.The reason is that Etch tries to download a file called Packages.diff which Sarge’s apt-proxy doesn’t know how to serve.

apt-proxy therefore log notes the following:

2007/02/09 10:10 CET [Channel,129,213.203.200.122] [debug] Request: GET /debian/dists/etch/main/binary-amd64/Packages.diff/Index
2007/02/09 10:10 CET [Channel,129,213.203.200.122] [debug] abort - unknown extension

Adding the following line to /etc/apt/apt.conf on your Etch machines will tell them not to download those files:

Acquire::PDiffs “false”;

ARSC Really Simple Chat

As my server crashed last week, I decided to not set up a homepage for my Open Source webchat project ARSC again.
It simply isn’t worth the hassle, because I didn’t do any work on ARSC for over 1 year now.

The SourceForge project page of ARSC is of course still active, and I don’t see any sense in deactivating it, because the latest stable release still works very well, supporting PHP4 and PHP5, MySQL 4 and 5, register_globals = Off and PHP’s safe_mode.

Decorators in PHP5

Until now I thought that decorating an object variable or method isn’t possible with PHP5, because __set, __get and __call, if you use them directly, are only working if you set or get variables (or call methods) that have not yet been defined.

But Ivo Jansch describes a nifty workaround by creating a forward class that overrides the built-in __set, __get and __call methods. This forward class can then be used to extend your decorator classes, allowing you to decorate variables and methods of your classes even if they have already been defined. Read the complete post here: Building proxies, decorators and delegates in PHP5.

« Previous PageNext Page »
Photograph of Manuel Kiessling
My XING profile
My LinkedIn profile