Elke dag een nieuwe backup van zeker een miljoen databases? Jazeker.

Alle OVH-webhostingplannen bevatten een of meer SQL-databases met inbegrepen gedeelde resources, en ook optionele databases met eigen resources, genaamd ‘Private SQL’. Beide soorten databases worden dagelijks door OVH gebackupt. Momenteel zijn dat iets meer dan een miljoen databases. Zulke grote aantallen brengen spannende uitdagingen met zich mee: hoe kunnen de backups na verloop van tijd het beste worden verspreid om piekbelasting op de infrastructuur te voorkomen? En welke methode is het beste voor de backups? Het database-team, dat hiervoor verantwoordelijk is bij OVH, kan deze vragen beantwoorden.

Wanneer maken we backups?

Het maken van backups zorgt natuurlijk voor een zwaardere belasting op de infrastructuur, of het nu gaat om databases of andere diensten. Dit is zeker van toepassing op input/output (I/O), omdat de data moet worden gekopieerd, en ook op netwerkniveau, omdat de data van de ene naar de andere computer moet worden overgedragen.

Deze problematiek is welbekend bij sysadmins, dus worden backups meestal gedaan op momenten dat de dienst het minst wordt gebruikt - meestal 's nachts.

In het verleden pasten we deze intuïtieve aanpak toe. Voor de overgrote meerderheid van gebruikers van OVH-webhosting ligt de off-peak periode tussen 01:00 en 07:00 ‘s ochtends (NL tijd). Database-backups werden dan ook ingepland binnen dit tijdsbestek.

Waarom werken wij dan vandaag de dag niet meer op deze manier? Omdat we ons al snel realiseerden dat deze aanpak op lange termijn te beperkend is. In het tijdvenster 01:00 - 07:00 waren onze systeem-indicatoren vaak knalrood. We ontdekten knelpunten; dumps (export van SQL-databases) duurden langer dan gepland. Dit bracht de kwaliteit van de dienst in gevaar, omdat de tijd die was gereserveerd voor backups regelmatig werd vertraagd. Het platform moest dus de backups proberen af te maken, terwijl het ook, tijdens de vroege ochtenduren, de groeiende stroom van bezoekers op de gehoste sites moest opvangen. Met andere woorden, het was niet haalbaar.

Daarom besloten we om een nieuwe methode te gebruiken en backup-taken te verspreiden over de gehele dag, om optimale prestaties te garanderen voor alle webhosting - overdag, én ‘s nachts.

Het distributiealgoritme

Om een gelijkmatige distributie van backups gedurende de dag mogelijk te maken, moesten we een tijdstip koppelen aan elke database.

We konden deze partitie (of ‘sharding’) niet uitvoeren met alleen de naam van de database, omdat een groot aantal databases in de infrastructuur simpelweg ‘wordpress’, ‘prestashop’, of zelfs ‘test’ of ‘demo’ zou worden genoemd. Dat betekende dat alle 'wordpress'-databases tegelijkertijd zouden zijn ondersteund, wat niet erg effectief zou zijn geweest.

Hoewel dit ongebruikelijk is, konden we ook niet sharden op basis van de naam van de door de database gehoste instance. Met veel minder instances dan databases, maakt de wet van de grote aantallen dat de distributie op de dag van de backups volgens de identiteit van de instances minder uniform zou zijn geweest dan een distributie in functie van de identiteit van de databases zelf. We hebben dus deze twee gegevens gecombineerd en vandaag gebruiken we de aaneenschakeling van de naam van de database en van de instance om onze sharding uit te voeren.

We hoefden alleen nog een formule te vinden die het mogelijk maakte om met deze reeks een uur van de dag te associëren, dat wil zeggen een getal tussen 1 en 1440 (het aantal minuten per dag). Met het getal 1440 dat deelbaar is door 16 (dankzij de Babyloniërs die voor de zeer deelbare basis 60 kozen voor het berekenen van de minuten en seconden), gebruikten we een eenvoudige hex-digest (digest) hash-functie (de sha512) om het befaamde nummer te genereren:

int(hashlib.sha512(instance_name + "." + db_name).hexdigest()[:90], 16) % 1440


De onderstaande grafiek toont aan dat de backups uniform worden verdeeld in de tijd.

Aantal geplande backups per 5 minuten.

Hoe voeren wij de backups uit?

Database-backups kunnen op twee manieren worden uitgevoerd: ofwel door de data in SQL-indeling te exporteren, of door de databases op te slaan in een indeling die leesbaar is voor het databasebeheersysteem (bijvoorbeeld DBMS of MySQL). Beide methoden hebben hun voordelen, nadelen, en gevallen van ongewoon gebruik. We hebben gekozen voor een combinatie van de twee methodes, dit om de voordelen van allebei samen te brengen.

Dumps

Het idee achter de dump-methode is om een tekstbestand met SQL-commando's te genereren die, wanneer ze teruggekoppeld worden naar de server, de database recreëren in dezelfde staat als ten tijde van de dump. Dit heeft het voordeel dat het de migratie van gegevens naar andere versies van de DBMS of andere engines mogelijk maakt. Het is ook mogelijk om het bestand handmatig te bewerken voordat het opnieuw wordt geïmporteerd (wat handig kan zijn als u een productieomgeving wilt klonen om tests uit te voeren, maar sommige omvangrijke tabellen bijvoorbeeld onbruikbaar zijn).

Met het oog op deze voordelen, passen we deze methode toe, en geven we u ook directe toegang tot de dumps, zichtbaar en rechtstreeks te downloaden vanaf het Control Panel. Zoals hierboven vermeld, worden de dumps dagelijks op een vast tijdstip uitgevoerd en blijven ze gedurende de lopende maand bewaard.

Om een dump consistent (dat wil zeggen, het geeft de status van de database op een gegeven moment weer) te houden kunnen we twee methoden inzetten:

Tabellen vergrendelen

De database wordt in een bepaalde staat gehouden en de verbindingen worden in de wachtrij geplaatst terwijl ze zich opstapelen. Zodra de dump is voltooid, ontgrendelen we de tafel en maken we de wachtrij vrij.

Voordelen: de methode is compatibel met alle engines (inclusief de belangrijkste, MyISAM en InnoDB) en de dump is altijd consistent.

Nadeel: de tabellen worden vergrendeld en het is noodzakelijk om te wachten tot het einde van de dump om de database (en dus de website) opnieuw toegankelijk te maken. Dit is in de meeste gevallen geen probleem, maar wel wanneer de dump omvangrijk is en er talrijke verbindingen zijn. De limiet voor het maximale aantal gelijktijdige verbindingen met de database kan dan worden bereikt. Merk op dat het vergroten van deze limiet het probleem niet oplost, maar het alleen een beetje uitstelt. Beperking van het aantal verbindingen beschermt ook uw server: voor een verbinding is RAM vereist. Zodra u meer dan 200 gelijktijdige verbindingen hebt gemaakt (het maximum dat is toegestaan voor SQL Private Instances), kan het RAM-geheugen dat is toegewezen aan de huidige verbindingen een Out Of Memory-fout veroorzaken.


Een transactie gebruiken

Voordelen: de dump is volledig transparant. Geen enkele vergrendeling. De dump blijft ook altijd consistent.

Nadelen: dit is alleen mogelijk met een engine die de transacties beheert (InnoDB). Dit betekent dat er slechts een enkele tabel zou bestaan in MyISAM en de dump incoherent zou zijn. Als u InnoDB gebruikt en er tijdens de dump een ALTER, CREATE, DROP, RENAME of TRUNCATE TABLE wordt uitgevoerd, is deze inconsistent.

Met het oog hierop hebben we de twee methodes gecombineerd: indien uw database 100% InnoDB is, dan gebruiken we een transactie. Zo niet, dan gebruiken we de vergrendeling van de tabellen.

Daarom raden we u ten zeerste aan om alle tabellen over te schakelen naar de InnoDB-indeling, welke is opgenomen en ingeschakeld in alle distributies die door MySQL AB sinds versie 4 worden geleverd en de standaard engine is geworden van MySQL 5.5.5 (zie de handleiding)!

Backups in DBMS-indeling

Het uitvoeren van een dump van een database brengt, zoals we hebben gezien, vele voordelen met zich mee in vergelijking met een ‘klassieke’ backup. De huidige methode vertoont niettemin een nadeel: de restauratietijd is afhankelijk van de omvang van de dump.

Met het dumpvolume dat we dagelijks creëren, kunnen we nauwkeurige statistieken opstellen over hoe lang het duurt om databases te exporteren en te herstellen. Hieronder volgt het resultaat van de lineaire regressies die we hebben berekend op basis van de responstijd van meer dan 40.000 100% InnoDB-basisexporten (een keuze waarbij geen rekening werd gehouden met de wachttijd voor de vergrendeling van de database).

$ ./lr.py list
y=0,142865163057*x1+4,65205077853
R2=0,792955

De dumptijd is afhankelijk van de grootte van de database, in MB.

R2 is hier de correlatiecoëfficiënt. Een waarde van 0,8 betekent dat de correlatie sterk is, dat wil zeggen dat het bepalen van de tijd van een dump op basis van de grootte van de database zinvol is, dat de twee waarden dus nauw verwant zijn.

We vroegen ons af of er andere parameters in aanmerking zijn genomen bij het bepalen van de dump- en restauratietijd. Daarom herhaalden we de oefening met verschillende variabelen. Aantal rijen, gemiddelde grootte van records... Uiteindelijk bestaat de enige nauwelijks relevantere berekening erin om rekening te houden met het aantal records (rijen) naast de grootte van de database:

$ ./lr.py list
y=2.62412392084*x1+0.130888461045*x2+4.60953501036
R2=0.800904

Dumptijd op basis van het aantal records (in miljoen) en de grootte van de database (in MB).

Aangemoedigd door deze bevindingen hebben we onze strategie aangepast om de hersteltijd van databases in geval van een incident in onze systemen te minimaliseren, omdat we weten dat een website die niet beschikbaar is meestal niet toegankelijk is, wat van cruciaal belang is voor de gebruiker. Dus, wanneer de grootte van een instance dat databases host groter is dan 4 GB (wat overeenkomt met een gemiddelde hersteltijd van 10 minuten), verdubbelen we systematisch de dumps van backups in DBMS-indeling. Dit heeft het voordeel van een veel snellere restauratie in geval van problemen op een opslagcluster. Deze backups, die worden uitgevoerd voor alle gedeelde instances die als host fungeren voor databases, en van geval tot geval voor private SQL-instances van meer dan 4 GB, zijn niet beschikbaar voor gebruikers; ze worden alleen gebruikt als er een probleem is op een opslagcluster. De gebruiker heeft ondertussen alleen toegang tot zijn dumps.

Voor het uitvoeren van deze backups in DBMS-indeling gebruiken we voor MySQL en MariaDB de XtraBackup-tool in de full-backup-modus (en niet in de incrementele modus) om het herstel te vergemakkelijken. XtraBackup is een opensource-tool van Percona en maakt het mogelijk om consistente backups te maken, zonder vergrendeling van de tabellen, ongeacht de gebruikte engine (MyISAM, InnoDB ...). Houd er rekening mee dat backups met XtraBackup worden uitgevoerd op de schaal van een volledige instance en niet van een eenvoudige database. Voor PostgreSQL gebruiken we het hulpprogramma pg_basebackup.

Verificatie van tabellen en RAM-vereisten

Voordat we een dump uitvoeren (dagelijks of op aanvraag), controleren we de status van uw tabellen en repareren deze indien nodig. Op MySQL- en MariaDB-instances gebruiken we daarvoor de opdracht mysqlcheck. Eén specifieke zorg verdwijnt geleidelijk: de nieuwste versies van MySQL en MariaDB zijn steeds beter in het beheren van schrijfbewerkingen die worden onderbroken door crashes, en dit probleem bestaat helemaal niet meer met PostgreSQL.

Voor de verificatie van een tabel, en met name de reparatie, is mogelijk veel meer RAM vereist dan waarover uw instance beschikt. Daarom verhogen we gedurende de hele tijd van mysqlcheck en de dump tijdelijk het RAM van uw instance met 4 GB. Als uw databases groot genoeg zijn, ziet u deze toevoeging van RAM in uw Control Panel:

In het geval dat dumps minder dan een minuut in beslag nemen, kan deze toevoeging van RAM tussen twee metingen onopgemerkt blijven. U zult het niet zien in de grafische weergave van uw Control Panel.

Opgemerkt moet worden dat dit piekgeheugen de grafiek overschrijft, waardoor de geheugengebruikscurve bijna onleesbaar is. Aarzel dus niet om onderaan de grafiek op ‘Maximale RAM-limiet’ te klikken om alleen de curve van geheugengebruik te doen verschijnen.

Waar slaan we de backups op?

Een backup is alleen nuttig als deze is opgeslagen op een platform van derden. We houden uw dumps ook op het Public Cloud Storage-platform, dat volledig losstaat van ons webhosting-databasebeheerplatform. Uw backups zijn op deze manier verspreid over drie synchrone replica's, die zich in drie verschillende incidentdomeinen bevinden, één in Gravelines, één in Roubaix en de laatste in Straatsburg. Ze worden er gedurende een maand opgeslagen.

De backups van XtraBackup en pg_basebackup van PrivateSQL op het platform van Parijs (webhosting aangemaakt vóór juli 2016) worden opgeslagen op een andere Ceph-cluster dan die gebruikt voor het opslaan van de productiegegevens. Tot slot worden backups van het Gravelines-platform (webhosting aangemaakt na juli 2016) opgeslagen op lokale harde schijven (en de productiegegevens op een Ceph-cluster).