Wie funktioniert das tägliche Backup von einer Million Datenbanken?
""Alle OVH Webhosting Angebote beinhalten als Inklusiv-Leistung eine oder mehrere SQL Datenbanken mit gemeinsam genutzten Ressourcen und darüber hinaus als Option auch die sogenannten „SQL Private“ Datenbanken mit eigenen Ressourcen. Beide Datenbanktypen werden täglich von OVH gesichert. Derzeit sind das insgesamt etwas mehr als eine Million Datenbanken. Bei einer so großen Anzahl ergeben sich spannende Herausforderungen: Wie verteilt man die Backups am geschicktesten über den Tag, um Lastspitzen auf der Infrastruktur zu vermeiden? Und welche Methode ist am besten für die Backups geeignet? Erklärungen von den zuständigen Experten bei OVH.
Wann führen wir die Backups durch? Wenn Backups durchgeführt werden – ganz gleich, ob es sich dabei um Datenbanken handelt oder um irgendeinen anderen Dienst – steigt natürlich die Belastung für die Infrastruktur. Dies gilt einerseits in Bezug auf Input/Output (I/O), weil die Daten kopiert werden müssen, und andererseits auch für das Netzwerk, weil die Daten von einer Maschine auf eine andere übertragen werden müssen. Dieses Problem ist Sysadmins natürlich bekannt. Deshalb werden Backups in der Regel zu Uhrzeiten durchgeführt, in denen die betreffende Dienstleistung am wenigsten genutzt wird – also normalerweise nachts. Auch wir hatten dieses intuitive Vorgehen ursprünglich übernommen.
Für die überwältigende Mehrheit der Nutzer von OVH Webhosting Angeboten liegt die Phase der geringsten Auslastung zwischen 01:00 und 07:00 Uhr morgens deutscher Zeit. Die Datenbank-Backups hatten wir also für genau diesen Zeitraum geplant. Aber weshalb gehen wir heute nicht mehr genauso vor? Weil diese Vorgehensweise schnell an ihre Grenzen stieß. Im Zeitfenster 01:00–07:00 Uhr leuchteten unsere Systemanzeigen oft rot auf. Es gab immer wieder Engpässe, Dumps (SQL-Datenbank-Exporte) dauerten länger als geplant und die Dienstqualität war ernsthaft in Gefahr, wenn das für die Backups vorgesehene Zeitfenster überschritten wurde. Die Plattform musste also nicht nur die Durchführung der Backups stemmen, sondern gleichzeitig den ab dem frühen Morgen zunehmenden Traffic durch die Besucher der gehosteten Websites bewältigen.
Mit anderen Worten: So konnte es nicht weitergehen. Wir haben uns daher für eine neue Methode entschieden und die Durchführung der Backups auf den gesamten Tag verteilt, um für alle Webhostings jederzeit eine optimale Performance zu gewährleisten – egal ob tagsüber oder mitten in der Nacht. Der Verteilungsalgorithmus Um die geplanten Backups gleichmäßig auf den Tag zu verteilen, mussten wir jeder Datenbank eine bestimmte Stunde zuweisen. Und diese Verteilung (das „Sharding“) konnten wir nicht einfach vom Namen der Datenbank abhängig machen. Auf der gesamten Infrastruktur gibt es nämlich schier unzählige Datenbanken mit den Namen „Wordpress“, „Prestashop“ oder auch „Test“ oder „Demo“. Wären wir rein nach der Benennung vorgegangen, hätten wir das Backup für alle Datenbanken mit dem Namen „Wordpress“ gleichzeitig gestartet – und das wäre nicht wirklich effizient gewesen.
Der Name der Instanz, auf der die Datenbank gehostet wird, ist zwar einzigartig, konnte aber ebenfalls nicht als alleinige Grundlage für das Sharding verwendet werden. Denn natürlich gibt es deutlich weniger Instanzen als Datenbanken. Entsprechend dem Gesetz der großen Zahlen wäre die Verteilung der Backups auf den Tag in Abhängigkeit von den Instanzen weniger gleichmäßig gewesen als eine Verteilung in Abhängigkeit von den Datenbanken selbst. Deshalb haben wir diese beiden Informationen miteinander kombiniert und verwenden heute eine Verknüpfung (genauer eine Konkatenation) der Namen von Datenbank und Instanz als Grundlage für das Sharding. Somit mussten wir nur noch eine Formel finden, um jeder Zeichenkette eine bestimmte Stunde des Tages zuzuweisen, genauer gesagt eine Zahl zwischen 1 und 1440 (die Anzahl der Minuten pro Tag). Da die Zahl 1440 durch 16 teilbar ist (den Babyloniern sei Dank für die Einführung der Zahl 60 als leicht teilbare Basis zur Berechnung von Minuten und Sekunden), haben wir eine einfache, hexadezimale kryptografische Hashfunktion (Digest, SHA-512) zur Erstellung des folgenden Algorithmus verwendet: int(hashlib.sha512(instance_name + ""."" + db_name).hexdigest()[:90], 16) % 1440 Der Verteilungsalgorithmus In der folgenden Grafik ist die gleichmäßige Verteilung der Backups über den Tag klar zu erkennen. Anzahl der geplanten Backups je 5 Minuten.
Wie führen wir die Backups durch? Für die Durchführung von Datenbank-Backups gibt es grundsätzlich zwei verschiedene Möglichkeiten. Entweder exportiert man die Daten im SQL-Format oder man erstellt die Backups in einem von dem jeweiligen Datenbankmanagementsystem lesbaren Format (DBMS, zum Beispiel MySQL). Beide Methoden haben ihre Vor- und Nachteile sowie typische Anwendungsbereiche. Wir haben uns auch hier für ein kombiniertes Verfahren entschieden, um so die Vorteile beider Methoden nutzen zu können.
Die Dumps Die Idee hinter dem Dump ist die Erstellung einer Textdatei mit SQL-Befehlen, die dann bei Bedarf dafür verwendet werden kann, die Datenbank ex nihilo in genau dem Zustand wiederherzustellen, in dem sie sich zum Zeitpunkt des Exports befunden hat. Der große Vorteil dabei ist, dass auch eine Datenmigration auf andere DBMS-Versionen oder sogar auf andere Engines möglich ist. Die Datei kann außerdem vor dem Reimport manuell bearbeitet werden (dies kann etwa nützlich sein, wenn man zu Testzwecken eine Produktionsumgebung klonen möchte, gewisse umfangreiche Tabellen dafür aber unnötig sind). Aufgrund dieser Vorteile verwenden wir diese Methode und geben Ihnen auch Zugriff auf die Dumps, die Sie direkt in Ihrem Kundencenter sehen und herunterladen können. Wie oben bereits beschrieben, werden diese Dumps jeden Tag zur gleichen Uhrzeit durchgeführt und jeweils einen Monat lang gespeichert. Damit jeder Dump konsistent ist (also den Zustand der Datenbank zu einem gegebenen Zeitpunkt perfekt widerspiegelt), gibt es wiederum zwei Methoden: Tabellen sperren
- Die Datenbank wird in einem bestimmten Zustand festgehalten, neue Verbindungen müssen warten und häufen sich an. Wenn der Dump abgeschlossen ist, werden die Tabellen wieder freigegeben und die anstehenden Verbindungen nach und nach abgearbeitet.
- Vorteile: Die Methode ist mit allen Engines kompatibel (also auch mit den wichtigsten, MyISAM und InnoDB) und der Dump ist immer konsistent.
- Nachteil: Die Tabellen sind gesperrt und die Datenbank (und damit die Website) ist erst nach Abschluss des Dumps wieder zugänglich. In den meisten Fällen verursacht das keine nennenswerten Probleme. Es kann allerdings problematisch werden, wenn die Erstellung des Dumps lange dauert und die Zahl der Verbindungen hoch ist. Dann kann unter Umständen die Obergrenze für die maximale Anzahl gleichzeitiger Verbindungen zur Datenbank erreicht werden. Hier ist anzumerken, dass eine Erhöhung dieser Obergrenze das Problem nicht lösen, sondern es lediglich verlagern würde. Außerdem dient diese maximale Verbindungsanzahl nicht zuletzt dem Schutz Ihrer Server: Jede Verbindung beansprucht den Arbeitsspeicher, und bei mehr als 200 Simultanverbindungen (das erlaubte Maximum für SQL Private Instanzen) könnte die Verwendung des RAM für laufende Verbindungen zu einem Out-of-Memory-Fehler auf Ihrer Instanz führen.
Eine Transaktion verwenden
- Vorteile: Der Dump ist vollkommen transparent. Keine Sperrung der Tabellen. Der Dump ist auch hier immer konsistent.
- Nachteile: Dieses Verfahren funktioniert nur mit Engines, die Transaktionen unterstützen (InnoDB). Mit anderen Worten: Wenn auch nur eine einzige Tabelle im MyISAM-Format vorliegt, wird der Dump inkonsistent. Und auch wenn ausschließlich Tabellen im InnoDB-Format vorhanden sind, kommt es zu einer Inkonsistenz, falls während des Dumps ein ALTER, CREATE, DROP, RENAME oder TRUNCATE TABLE durchgeführt wird.
Angesichts all dieser Punkte haben wir erneut beide Methoden kombiniert: Wenn Ihre Datenbank 100 % InnoDB ist, verwenden wir eine Transaktion. Andernfalls sperren wir die Tabellen. Aus genau diesem Grund möchten wir Ihnen auch sehr ans Herz legen, alle Ihre Tabellen in das Format InnoDB zu konvertieren, das bei allen Distributionen von MySQL AB ab Version 4 inklusive und aktiviert ist und ab MySQL 5.5.5 sogar als Standard-Engine verwendet wird (zur Anleitung). Backups im Format des DBMS Wie wir gesehen haben, birgt die Erstellung eines Dumps zur Datenbanksicherung zahlreiche Vorteile im Vergleich mit einem „klassischen“ Backup. Allerdings hat die Methode auch einen Nachteil: die Wiederherstellungsdauer, die von der Größe des Dumps abhängt.
Aufgrund der Vielzahl an Dumps, die wir täglich ausführen, konnten wir präzise Statistiken zur Dauer von Datenbankexporten und -wiederherstellungen erstellen. Sie finden unten das Ergebnis der linearen Regressionen, die wir für die Antwortzeit von mehr als 40.000 Datenbankexporten errechnet haben. Hier wurden nur Datenbanken mit 100 % InnoDB miteinbezogen, um so keine Wartezeit bis zur Sperrung der Datenbank berücksichtigen zu müssen.
$ ./lr.py list y=0.142865163057*x1+4.65205077853 R2=0.792955
Dauer des Dumps in Abhängigkeit von der Datenbankgröße (in MB)
R2 ist hier der Korrelationskoeffizient. Ein Wert von 0,8 bedeutet, dass die Korrelation stark ist. Oder mit anderen Worten, dass die Berechnung der Dauer eines Dumps in Abhängigkeit von der Datenbankgröße sinnvoll ist und die beiden Werte miteinander in unmittelbarem Zusammenhang stehen. Wir haben uns dann gefragt, ob noch andere Parameter für die Berechnung der Dauer eines Dumps und der Wiederherstellung von Bedeutung sind. Also haben wir die Berechnung mit einigen anderen Variablen angestellt (Anzahl der Rows, durchschnittliche Größe der Datensätze, ...) Am Ende hat es sich dann als sinnvoll erwiesen, zusätzlich zur Größe der Datenbank auch die Anzahl der Datensätze (Rows) zu berücksichtigen:
$ ./lr.py list y=2.62412392084*x1+0.130888461045*x2+4.60953501036 R2=0.800904
Dauer des Dumps in Abhängigkeit von der Anzahl der Datensätze (in Millionen) sowie der Datenbankgröße (in MB)
Auf Grundlage dieser Erkenntnisse haben wir unsere Strategie so angepasst, dass die Zeit für die Datenbankwiederherstellung im Falle einer Störung auf unseren Systemen minimiert wird. Denn wir wissen, dass eine nicht verfügbare Datenbank normalerweise bedeutet, dass auch die zugehörige Website nicht erreichbar ist – ein kritischer Punkt für die Nutzer. Wenn die Größe einer Instanz, auf der Datenbanken gehostet sind, eine Grenze von 4 GB übersteigt (dies entspricht einer durchschnittlichen Wiederherstellungsdauer von 10 Minuten), verdoppeln wir systematisch die Dumps im DBMS-Format. So kann bei Problemen auf einem Storage-Cluster die Wiederherstellung entscheidend beschleunigt werden. Diese zusätzlichen Backups, die wir für alle Shared Hosting Instanzen mit Datenbanken anfertigen (sowie von Fall zu Fall für SQL Private Instanzen mit mehr als 4 GB), stehen unseren Nutzern allerdings nicht zur Verfügung. Sie kommen nur bei Problemen auf einem Storage-Cluster zum Einsatz. Der Nutzer hat seinerseits nur Zugriff auf seine eigenen Dumps.
Um diese Backups im DBMS-Format anzufertigen, verwenden wir für MySQL und MariaDB das Tool XtraBackup im Full-Backup-Modus (nicht im inkrementellen Modus), um die Wiederherstellung zu vereinfachen. XtraBackup ist ein Open-Source-Tool von Percona, das konsistente Backups ohne Sperrung der Tabellen ermöglicht – und das unabhängig von der verwendeten Engine (MyISAM, InnoDB, …). Dabei werden die Sicherungen mit XtraBackup immer für eine vollständige Instanz und nicht für einzelne Datenbanken durchgeführt. Für PostgreSQL verwenden wir pg_basebackup. Überprüfung der Tabellen und RAM-Bedarf Bevor wir einen Dump durchführen (sei es die tägliche Sicherung oder on demand), überprüfen wir den Zustand Ihrer Tabellen und reparieren sie bei Bedarf. Auf MySQL und MariaDB Instanzen verwenden wir hierfür den Befehl mysqlcheck. Hierbei handelt es sich allerdings um ein Problem, das immer seltener auftritt: Die jüngsten Versionen von MySQL und MariaDB können durch Crashes unterbrochene Write-Operationen immer besser fertigstellen, und bei PostgreSQL existiert das Problem überhaupt nicht mehr. Die Überprüfung einer Tabelle und vor allem ihre Reparatur kann allerdings deutlich mehr RAM in Anspruch nehmen, als Ihrer Instanz normalerweise zur Verfügung steht.
Aus diesem Grund erhöhen wir für die Dauer des mysqlcheck und des Dumps vorübergehend den zur Verfügung stehenden RAM Ihrer Instanz um 4 GB. Wenn Ihre Datenbanken groß genug sind, ist dieser zusätzliche RAM in Ihrem Kundencenter für Sie sichtbar: Wenn die Durchführung des Dumps weniger als 1 Minute dauert, kann die Erhöhung des RAM dagegen genau auf den Zeitraum zwischen zwei Messungen beschränkt sein. In diesem Fall ist die zeitweilige Änderung für Sie in den Graphen in Ihrem Kundencenter nicht sichtbar. Hier ist noch anzumerken, dass diese kurzfristige Erhöhung des Arbeitsspeichers den Graphen unter Umständen unlesbar macht, weil die Details der Nutzungskurve nicht mehr erkennbar sind. In diesem Fall können Sie aber einfach unterhalb des Graphen auf „Maximales RAM-Limit“ klicken, damit nur noch die RAM-Verwendung angezeigt und somit wieder lesbar wird. Wo speichern wir eigentlich die Backups? Ein Backup ist nur dann wirklich sinnvoll, wenn es auf einer Drittplattform gespeichert wird. Deshalb speichern wir Ihre Dumps auf der Public Cloud Storage Plattform, die vollkommen unabhängig von den Plattformen ist, die wir für die Verwaltung der Datenbanken im Bereich Webhosting einsetzen. So sind Ihre Backups auf drei synchrone Replikate an drei verschiedenen Orten verteilt, in Gravelines, in Roubaix und in Straßburg – und damit sind Sie optimal vor Störungen und Ausfällen geschützt! Ihre Dumps werden dort für jeweils einen Monat gespeichert. Die Backups XtraBackup und pg_basebackup des Angebots SQL Private auf der Plattform in Paris (Webhostings, die vor Juli 2016 erstellt wurden) werden in einem eigenen Ceph-Cluster gespeichert – vollkommen unabhängig von dem, in dem die Produktionsdaten gespeichert sind. Die Backups der Plattform in Gravelines (Webhostings, die nach Juli 2016 erstellt wurden) werden schließlich auf lokalen Festplatten gespeichert (und die Produktionsdaten in einem Ceph-Cluster). Wir stellen ein! Sie interessieren sich für diese Themen? Wir sind immer auf der Suche nach neuen Talenten! Unsere aktuellen Ausschreibungen finden Sie auf OVH Careers! ""