Architektur der Speicherung und Ausgabe von Fotos in Badoo

Architektur der Speicherung und Ausgabe von Fotos in Badoo

Artem Denisov ( bo0rsh201, Badoo)

Badoo ist die größte Dating-Website der Welt. Momentan haben wir etwa 330 Millionen Nutzer weltweit registriert. Doch was in unserem heutigen Gespräch viel wichtiger ist, ist die Tatsache, dass wir ungefähr 3 Petabyte an Nutzerdaten speichern. Jeden Tag laden unsere Nutzer etwa 3,5 Millionen neue Fotos hoch, und die Leselast beträgt etwa 80.000 Anfragen pro Sekunde. Das ist ziemlich viel für unser Backend, und manchmal gibt es dabei Herausforderungen.

Architektur der Speicherung und Ausgabe von Fotos in Badoo

Ich werde über das Design dieses Systems sprechen, das die Fotos insgesamt speichert und bereitstellt, und ich werde einen Entwicklerblick darauf werfen. Es wird eine kurze Retrospektive darüber geben, wie es sich entwickelt hat, wo ich die wichtigsten Meilensteine aufzeigen werde, aber ich werde nur ausführlich über die Lösungen sprechen, die wir jetzt verwenden.

Jetzt lass uns anfangen.

Video abspielen

Wie ich bereits sagte, wird dies eine Retrospektive sein, und um sie zu beginnen, lasst uns ein ganz banales Beispiel nehmen.

Architektur der Speicherung und Ausgabe von Fotos in Badoo

Wir haben eine allgemeine Aufgabe, wir müssen die Fotos der Nutzer empfangen, speichern und bereitstellen. In dieser Form ist die Aufgabe allgemein, wir können alles Mögliche verwenden:

  • moderne Cloud-Speicher,
  • Fertigungslösungen, von denen es jetzt auch viele gibt;
  • wir können mehrere Maschinen in unserem Rechenzentrum einrichten und große Festplatten darauf installieren und die Fotos dort speichern.

Badoo lebt historisch — sowohl jetzt als auch damals (zur Zeit des Entstehens) — auf eigenen Servern, innerhalb unserer eigenen Rechenzentren. Daher war diese Option für uns optimal.

Architektur der Speicherung und Ausgabe von Fotos in Badoo

Wir haben einfach mehrere Maschinen genommen, sie "photos" genannt, und so haben wir einen Cluster erstellt, der die Fotos speichert. Aber es scheint, als würde etwas fehlen. Damit das alles funktioniert, muss man irgendwie bestimmen, auf welcher Maschine welche Fotos gespeichert werden. Und hier muss man auch nicht das Rad neu erfinden.

Architektur der Speicherung und Ausgabe von Fotos in Badoo

Wir fügen in unser Speichersystem mit Informationen über die Nutzer ein Feld hinzu. Das wird der Sharding-Schlüssel sein. In unserem Fall haben wir es place_id genannt, und diese ID des Ortes gibt an, wo die Fotos der Nutzer gespeichert werden. Wir erstellen Karten.

In der ersten Phase kann man das sogar von Hand machen – wir sagen, dass das Foto dieses Benutzers mit diesem Standort auf diesem Server gespeichert wird. Dank dieser Karte wissen wir immer, wann ein Benutzer ein Foto hochlädt, wo wir es speichern und von wo wir es zurückgeben können.

Es ist ein absolut triviales Schema, aber es hat einige ziemlich wesentliche Vorteile. Erstens – es ist einfach, wie ich bereits gesagt habe, und zweitens – mit diesem Ansatz können wir leicht horizontal skalieren, indem wir einfach neue Maschinen bereitstellen und sie in die Karte aufnehmen. Es gibt nichts weiter zu tun.

So war es eine Zeit lang bei uns.

Architektur der Speicherung und Ausgabe von Fotos in Badoo

Das war ungefähr im Jahr 2009. Wir haben Autos geliefert, geliefert…

Und irgendwann bemerkten wir, dass dieses Schema bestimmte Nachteile hatte. Welche Nachteile?

In erster Linie ist es die begrenzte Kapazität. Auf einen physischen Server können wir nicht so viele Festplatten unterbringen, wie wir gerne hätten. Und das wurde mit der Zeit und dem Wachstum des Datensatzes zu einem bestimmten Problem.

Und zweitens. Es ist eine untypische Maschinenkonfiguration, da solche Maschinen schwer in anderen Clustern wiederverwendet werden können; sie sind recht spezifisch, das heißt, sie sollten leistungsschwach sein, aber gleichzeitig große Festplatten besitzen.

Das alles war 2009 der Fall, aber im Prinzip sind diese Anforderungen bis heute relevant. Wir haben eine Rückschau, sodass es 2009 in dieser Hinsicht wirklich schlecht war.

Und der letzte Punkt – der Preis.

Architektur der Speicherung und Ausgabe von Fotos in Badoo

Der Preis war damals sehr hoch, und wir mussten nach Alternativen suchen. Das heißt, wir mussten einen besseren Umgang mit dem Platz in den Rechenzentren und den physischen Servern finden, auf denen das alles läuft. Unsere Systemingenieure begannen mit umfassenden Untersuchungen und überdachten viele verschiedene Optionen. Sie schauten sich auch Clusterdateisysteme wie PolyCeph und Lustre an. Dort gab es Probleme mit der Leistung und eine recht komplexe Wartung. Sie haben es aufgegeben. Sie haben versucht, den gesamten Datensatz über NFS auf jede Maschine zu mounten, um auf diese Weise irgendwie zu skalieren. Das Lesen hat sich ebenfalls als problematisch erwiesen, sie haben verschiedene Lösungen von verschiedenen Anbietern ausprobiert.

Am Ende haben wir uns darauf geeinigt, dass wir das sogenannte Storage Area Network verwenden.

Architektur der Speicherung und Ausgabe von Fotos in Badoo

Das sind große SHDs, die darauf ausgelegt sind, große Datenmengen zu speichern. Sie bestehen aus Regalen mit Festplatten, die an die Endgeräte über Optik angeschlossen sind. So haben wir einen relativ kleinen Pool an Maschinen, und diese SHDs sind für unsere Abgabelogik transparent, das heißt, für unser Nginx oder andere, die die Anfragen nach diesen Fotos bedienen.

Diese Lösung hatte offensichtliche Vorteile. Es handelt sich um SHDs, die darauf ausgelegt sind, Fotos zu speichern. Das ist günstiger, als wenn wir Maschinen mit Festplatten einrichten.

Der zweite Vorteil.

Architektur der Speicherung und Ausgabe von Fotos in Badoo

Das ist die erhöhte Kapazität, d.h. wir können viel mehr Speicher in viel geringerem Volumen unterbringen.

Aber es gab auch Nachteile, die ziemlich schnell bemerkbar wurden. Mit dem Wachstum der Nutzerzahl und der Last auf dieses System traten Leistungsprobleme auf. Und das Problem ist ziemlich offensichtlich – jede SHD, die darauf ausgelegt ist, viele Fotos in kleinem Volumen zu speichern, leidet in der Regel unter intensivem Lesen. Das gilt auch für jeden Cloud-Speicher und was auch immer. Es gibt derzeit keinen perfekten Speicher, der unendlich skalierbar ist, in den man alles hineinstecken kann und der gut mit Lesevorgängen zurechtkommt. Besonders mit zufälligen Lesevorgängen.

Architektur der Speicherung und Ausgabe von Fotos in Badoo

Wie im Falle unserer Fotos, weil die Fotos nicht sequenziell angefordert werden, was sich stark auf ihre Leistung auswirkt.

Selbst nach den heutigen Zahlen, wenn wir irgendwo über 500 RPS für Fotos pro Maschine, die mit dem Speicher verbunden ist, haben, treten bereits Probleme auf. Das war für uns ziemlich schlecht, weil die Anzahl der Nutzer steigt und alles schlimmer wird. Das muss irgendwie optimiert werden.

Um zu optimieren, haben wir damals beschlossen, uns offensichtlich das Lastprofil anzusehen – was überhaupt passiert ist und was optimiert werden muss.

Architektur der Speicherung und Ausgabe von Fotos in Badoo

Und hier spielt alles in unsere Hände.

Ich habe bereits in der ersten Folie gesagt: Wir haben 80.000 Leseanfragen pro Sekunde bei insgesamt 3,5 Millionen Uploads pro Tag. Das ist ein Unterschied von drei Größenordnungen. Es ist offensichtlich, dass das Lesen optimiert werden muss und praktisch klar ist, wie.

Es gibt noch einen kleinen Punkt. Die Besonderheit des Services ist, dass sich der Nutzer registriert, ein Foto hochlädt, dann aktiv andere Personen anschaut, ihnen gefällt und er anderen aktiv gezeigt wird. Danach findet er einen Partner oder auch nicht, wie es eben kommt, und nutzt den Service für eine Weile nicht mehr. In diesem Moment, in dem er aktiv ist, sind seine Fotos sehr gefragt – sie werden von vielen Menschen angesehen. Sobald er damit aufhört, wird er ziemlich schnell aus den intensiven Anzeigen für andere Menschen herausgenommen, wie es vorher war, und seine Fotos werden kaum noch angefragt.

Architektur der Speicherung und Ausgabe von Fotos in Badoo

Das heißt, wir haben einen sehr kleinen heißen Datensatz. Aber gleichzeitig gibt es dafür sehr viele Anfragen. Daher liegt es nahe, einen Cache hinzuzufügen.

Ein LRU-Cache löst all unsere Probleme. Was machen wir?

Architektur der Speicherung und Ausgabe von Fotos in Badoo

Wir fügen vor unserem großen Cluster mit dem Storage noch einen vergleichsweise kleinen hinzu, der als Fotoscache (photoscache) bezeichnet wird. Das ist im Wesentlichen einfach ein cacheproxy.

Wie funktioniert das intern? Hier ist unser Nutzer, da ist der Storage. Alles wie früher. Was fügen wir zwischen ihnen hinzu?

Architektur der Speicherung und Ausgabe von Fotos in Badoo

Das ist einfach eine Maschine mit einer schnellen physischen Festplatte. Nehmen wir eine SSD. Und auf dieser Festplatte wird ein lokaler Cache gespeichert.

Wie sieht das aus? Der Nutzer sendet eine Anfrage nach einem Foto. NGINX sucht zuerst in dem lokalen Cache danach. Wenn es nicht da ist, macht es einfach einen proxy_pass auf unseren Storage, lädt das Foto von dort herunter und gibt es dem Nutzer.

Aber das ist sehr banal und unverständlich, was im Inneren passiert. So funktioniert es etwa.

Architektur der Speicherung und Ausgabe von Fotos in Badoo

Der Cache ist logisch in drei Ebenen unterteilt. Wenn ich "drei Ebenen" sage, bedeutet das nicht, dass es ein komplexes System gibt. Nein, es sind einfach drei Verzeichnisse im Dateisystem:

  1. Das ist der Puffer, in den gerade aus dem Proxy hochgeladene Fotos gelangen.
  2. Das ist der heiße Cache, in dem aktuell häufig angefragte Fotos gespeichert werden.
  3. Und der kalte Cache, in den Fotos schrittweise aus dem heißen Cache gedrängt werden, wenn weniger Anfragen zu ihnen kommen.

Damit das funktioniert, müssen wir diesen Cache irgendwie verwalten, Fotos darin verschieben usw. Das ist ebenfalls ein sehr einfacher Prozess.

Architektur der Speicherung und Ausgabe von Fotos in Badoo

Nginx schreibt einfach für jede Anfrage in das RAMDisk access.log, in dem der Pfad zum Bild, das er gerade bedient hat (natürlich der relative Pfad), und welcher Abschnitt es bedient hat, angegeben ist. Das heißt, dort könnte stehen „Foto 1“ und weiter entweder ein Puffer, ein heißer Cache, ein kalter Cache oder ein Proxy.

Je nach dem müssen wir entscheiden, was mit dem Bild zu tun ist.

Auf jeder Maschine läuft ein kleiner Daemon, der ständig dieses Log ausliest und in seinem Speicher Statistiken über die Nutzung der jeweiligen Bilder speichert.

Architektur der Speicherung und Ausgabe von Fotos in Badoo

Er sammelt einfach dort, führt Zähler und macht periodisch Folgendes. Aktiv angeforderte Bilder, für die viele Anfragen kommen, verschiebt er in den heißen Cache, wo auch immer sie abgelegt sind.

Architektur der Speicherung und Ausgabe von Fotos in Badoo

Bilder, die selten angefordert werden und noch seltener angefordert werden, schiebt er schrittweise aus dem heißen Cache in den kalten.

Architektur der Speicherung und Ausgabe von Fotos in Badoo

Und wenn unser Cache voll ist, beginnen wir einfach, alles ohne Unterscheidung aus dem kalten Cache zu löschen. Und das funktioniert übrigens gut.

Damit das Bild sofort bei der Proxyierung im Puffer gespeichert wird, verwenden wir die Direktive proxy_store, und der Puffer ist ebenfalls ein RAMDisk, d.h. für den Benutzer funktioniert es sehr schnell. Das betrifft die Details des cachenden Servers.

Es bleibt die Frage, wie wir die Anfragen auf diese Server verteilen.

Angenommen, es gibt einen Cluster aus zwanzig Storage-Maschinen und drei cachenden Servern (so ist es dazu gekommen).

Architektur der Speicherung und Ausgabe von Fotos in Badoo

Wir müssen irgendwie bestimmen, welche Anfragen nach welchen Bildern und wohin sie geleitet werden sollen.

Die einfachste Variante ist Round Robin. Oder sollte man es zufällig machen?

Das hat offensichtlich eine Reihe von Nachteilen, da wir in einer solchen Situation den Cache sehr ineffizient nutzen werden. Anfragen werden auf irgendwelche zufälligen Maschinen geleitet: hier wurde es zwischengespeichert, nebenan ist es schon nicht mehr da. Und das wird, falls es funktioniert, sehr schlecht sein. Sogar bei einer geringen Anzahl von Maschinen im Cluster.

Wir müssen irgendwie eindeutig bestimmen, auf welchen Server welche Anfrage geleitet wird.

Es gibt eine simple Methode. Wir nehmen den Hash von der URL oder den Hash von unserem Sharding-Schlüssel, der in der URL enthalten ist, und teilen ihn ganzzahlig durch die Anzahl der Server. Wird das funktionieren? Ja.

Architektur der Speicherung und Ausgabe von Fotos in Badoo

Das heißt, wir haben eine hundertprozentige Anfrage, zum Beispiel bei einer bestimmten "example_url" landet sie immer auf dem Server mit dem Index "2", und der Cache wird ständig so gut wie möglich genutzt.

Aber es gibt ein Problem mit dem Resharding in diesem Schema. Resharding – ich meine die Veränderung der Anzahl der Server.

Angenommen, unser Cache-Cluster kann nicht mehr mithalten, und wir haben beschlossen, eine weitere Maschine hinzuzufügen.

Wir fügen hinzu.

Architektur der Speicherung und Ausgabe von Fotos in Badoo

Jetzt teilen wir alles nicht mehr durch drei, sondern durch vier. Somit leben praktisch alle Schlüssel, die wir zuvor hatten, fast alle URLs jetzt auf anderen Servern. Der gesamte Cache wurde einfach im Augenblick ungültig. Alle Anfragen strömten auf unser Cluster-Storage, es wurde schlimm, Dienstleisterausfälle und unzufriedene Benutzer. So möchte ich es nicht machen.

Diese Option passt uns auch nicht.

Was müssen wir also tun? Wir müssen somehow effizient den Cache nutzen, ständig eine Anfrage auf denselben Server leiten, während wir gleichzeitig resistent gegen Resharding sind. Und es gibt eine solche Lösung, die nicht allzu kompliziert ist. Sie heißt konsistentes Hashing.

Architektur der Speicherung und Ausgabe von Fotos in Badoo

Wie sieht das aus?

Architektur der Speicherung und Ausgabe von Fotos in Badoo

Wir nehmen irgendeine Funktion vom Sharding-Schlüssel und verteilen alle ihre Werte gleichmäßig auf einem Kreis. Das heißt, an Punkt 0 treffen sich die minimalen und maximalen Werte. Dann platzieren wir auf demselben Kreis all unsere Server ungefähr wie folgt:

Architektur der Speicherung und Ausgabe von Fotos in Badoo

Jeder Server wird durch einen Punkt definiert, und der Sektor, der im Uhrzeigersinn bis zu ihm geht, wird entsprechend von diesem Host bedient. Wenn wir Anfragen erhalten, sehen wir sofort, dass beispielsweise Anfrage A – ihr Hash sieht so aus – und sie wird von Server 2 bedient. Anfrage B – von Server 3. Und so weiter.

Architektur der Speicherung und Ausgabe von Fotos in Badoo

Was passiert in dieser Situation beim Resharding?

Architektur der Speicherung und Ausgabe von Fotos in Badoo

Wir invalidieren nicht den gesamten Cache, wie früher, und verschieben nicht alle Schlüssel, sondern verschieben jeden Sektor um eine kleine Distanz, sodass in den freigewordenen Platz, um es so zu sagen, unser sechster Server, den wir hinzufügen möchten, passt und wir ihn dort hinzufügen.

Architektur der Speicherung und Ausgabe von Fotos in Badoo

In einer solchen Situation geraten die Schlüssel tatsächlich ins Wanken. Aber sie wackeln deutlich weniger als früher. Und wir sehen, dass unsere beiden ersten Schlüssel auf ihren Servern geblieben sind, während sich der caching-Server nur für den letzten Schlüssel geändert hat. Das funktioniert ziemlich effektiv, und wenn Sie schrittweise neue Hosts hinzufügen, gibt es hier kein großes Problem. Sie fügen nach und nach hinzu, warten, bis der Cache wieder gefüllt ist, und alles funktioniert gut.

Die einzige Frage bleibt bei Ausfällen. Angenommen, wir haben einen Ausfall eines bestimmten Geräts.

Architektur der Speicherung und Ausgabe von Fotos in Badoo

Und in diesem Moment möchten wir eigentlich nicht diese Karte neu generieren, einen Teil des Caches ungültig machen und so weiter, falls beispielsweise die Maschine neu gestartet werden musste, wir aber irgendwie die Anfragen bedienen müssen. Wir halten einfach an jedem Standort einen Reserve-Foto-Cache bereit, der als Ersatz für jedes Gerät dient, das derzeit ausgefallen ist. Wenn plötzlich ein Server nicht mehr verfügbar ist, geht der Verkehr dorthin. In diesem Fall haben wir natürlich keinen Cache, d.h. er ist kalt, aber zumindest werden die Nutzeranfragen bearbeitet. Wenn es sich um einen kurzen Zeitraum handelt, überstehen wir das ganz problemlos. Es lastet einfach mehr auf dem Speicher. Wenn der Zeitraum länger ist, können wir bereits entscheiden — ob wir diesen Server von der Karte entfernen oder nicht, oder vielleicht durch einen anderen ersetzen.

Das ist zur Cache-System. Lassen Sie uns die Ergebnisse betrachten.

Es scheint eigentlich nichts Kompliziertes dabei zu sein. Aber diese Art der Cache-Verwaltung hat uns eine Trefferquote von etwa 98 % eingebracht. D.h. von diesen 80.000 Anfragen pro Sekunde erreichen nur 1.600 die Speichersysteme, und das ist eine völlig normale Last, die sie problemlos bewältigen können, wir haben immer einen Puffer.

Wir haben diese Server in unseren drei Rechenzentren platziert und damit drei Standorte erhalten — Prag, Miami und Hongkong.

Architektur der Speicherung und Ausgabe von Fotos in Badoo

Somit sind sie mehr oder weniger lokal zu jedem unserer Zielmärkte positioniert.

Und als angenehmer Bonus haben wir diesen caching-Proxy erhalten, auf dem die CPU eigentlich ungenutzt ist, weil sie für die Bereitstellung von Inhalten nicht so stark benötigt wird. Und dort haben wir mit NGINX+ Lua sehr viel nützliche Logik umgesetzt.

Architektur der Speicherung und Ausgabe von Fotos in Badoo

Zum Beispiel können wir mit webp oder progressiven jpeg experimentieren (das sind moderne, effiziente Formate), sehen, wie sich das auf den Traffic auswirkt, Entscheidungen treffen, es für bestimmte Länder aktivieren usw.; dynamisches Resize oder Cropping von Fotos in Echtzeit durchführen.

Das ist ein guter Use Case, wenn Sie zum Beispiel eine mobile Anwendung haben, die Fotos anzeigt, und die mobile Anwendung CPU-Leistung des Geräts nicht aufwenden möchte, um ein großes Foto anzufordern und es dann auf eine bestimmte Größe zu bringen, um es in das View zu bringen. Wir können einfach dynamisch in der URL irgendwelche Parameter im UPort festlegen, und der Fotocache resized das Foto automatisch. In der Regel wählt er die Größe aus, die wir physisch auf der Festplatte haben und die der angeforderten am nächsten kommt, und er skaliert sie dann in den entsprechenden Koordinaten herunter.

Übrigens haben wir die Videoaufzeichnungen der letzten fünf Jahre der Konferenz für Entwickler hochbelasteter Systeme veröffentlicht. HighLoad++. Schauen Sie sich um, lernen Sie, teilen Sie und abonnieren Sie unseren YouTube-Kanal..

Wir können auch viele Produktlogik hinzufügen. Zum Beispiel können wir je nach URL-Parametern verschiedene Wasserzeichen hinzufügen, Fotos verwischen, vernebeln oder pixeln. Das ist nützlich, wenn wir ein Foto einer Person zeigen wollen, aber deren Gesicht nicht zeigen möchten, das funktioniert gut, und das ist hier alles implementiert.

Was haben wir erreicht? Wir haben drei Präsenzpunkte, eine gute Hitquote und dabei bleibt die CPU auf diesen Maschinen nicht ungenutzt. Sie ist jetzt natürlich wichtiger als früher. Wir müssen leistungsstärkere Maschinen installieren, aber das ist es wert.

Das betrifft die Bereitstellung von Fotos. Hier ist alles ziemlich klar und offensichtlich. Ich denke nicht, dass ich hier eine neue Erkenntnis präsentiere, so funktioniert praktisch jedes CDN.

Und wahrscheinlich könnte ein erfahrener Zuhörer sich die Frage stellen: Warum nicht einfach alles auf ein CDN umstellen? Das wäre ungefähr das Gleiche, alle modernen CDNs können das. Es gibt allerdings mehrere Gründe dafür.

Der erste Grund sind die Fotos.

Architektur der Speicherung und Ausgabe von Fotos in Badoo

Das ist einer der wichtigsten Punkte unserer Infrastruktur, und wir müssen so viel Kontrolle über sie wie möglich haben. Wenn es sich um eine Lösung eines Drittanbieters handelt und Sie in keiner Weise die Kontrolle darüber haben, wird es für Sie ziemlich schwierig, damit umzugehen, wenn Sie einen großen Datensatz haben und einen sehr hohen Anfrageaufkommen von Nutzern.

Ich gebe ein Beispiel. Momentan können wir in unserer Infrastruktur, im Falle von Problemen oder unterirdischen Geräuschen, auf die Maschine zugreifen und uns dort debugging-technisch betätigen, sozusagen. Wir können Metriken sammeln, die nur für uns wichtig sind, wir können experimentieren und sehen, wie sich das auf die Grafiken auswirkt und so weiter. Momentan wird sehr viel Statistik über diesen caching Cluster gesammelt. Und wir beobachten sie regelmäßig und untersuchen lange Zeit bestimmte Anomalien. Wenn das auf der CD-Seite wäre, wäre es viel schwieriger zu kontrollieren. Oder, wenn ein Unfall passiert, wissen wir, was passiert ist, wir wissen, wie wir damit umgehen und wie wir es bekämpfen können. Das ist die erste Schlussfolgerung.

Die zweite Schlussfolgerung ist auch eher historisch, da das System sich schon lange entwickelt und viele verschiedene Geschäftsanforderungen in verschiedenen Phasen bestanden haben, die nicht immer in das Konzept eines CDNs passen.

Und der Punkt, der sich aus dem vorherigen ergibt –

Architektur der Speicherung und Ausgabe von Fotos in Badoo

Das ist, dass wir bei den Foto-Caches viel spezifische Logik haben, die nicht immer auf Anfrage hinzugefügt werden kann. Es ist unwahrscheinlich, dass irgendein CDN auf Ihre Anfrage hin maßgeschneiderte Dinge für Sie hinzufügt. Zum Beispiel die Verschlüsselung von URLs, wenn Sie nicht möchten, dass der Kunde etwas ändern kann. Sie möchten die URL auf dem Server ändern und sie verschlüsseln, und dann hier einige dynamische Parameter übergeben.

Welche Schlussfolgerung drängt sich auf? In unserem Fall ist CDN keine sehr gute Alternative.

Architektur der Speicherung und Ausgabe von Fotos in Badoo

In Ihrem Fall, wenn Sie spezielle Geschäftsanforderungen haben, können Sie völlig entspannt das implementieren, was ich Ihnen gezeigt habe. Und das wird bei einem ähnlichen Lastprofil hervorragend funktionieren.

Aber wenn Sie eine allgemeine Lösung haben und die Aufgabe nicht sehr speziell ist, können Sie problemlos ein CDN nutzen. Oder wenn für Sie die Zeit und die Ressourcen wichtiger sind als die Kontrolle.

Architektur der Speicherung und Ausgabe von Fotos in Badoo

Moderne CDNs bieten praktisch alles, was ich Ihnen gerade erzählt habe. Mit Ausnahme von ein paar speziellen Funktionen.

Das betrifft die Auslieferung von Bildern.

Lassen Sie uns jetzt ein wenig in unserer Rückschau voranschreiten und über die Speicherung sprechen.

Das Jahr 2013 war.

Architektur der Speicherung und Ausgabe von Fotos in Badoo

Die Cache-Server wurden hinzugefügt, die Performance-Probleme sind verschwunden. Alles ist gut. Der Datensatz wächst. Im Jahr 2013 hatten wir etwa 80 Server, die mit Storages verbunden sind, und etwa 40 Cache-Server in jedem Rechenzentrum. Das sind 560 Terabyte Daten in jedem Rechenzentrum, also insgesamt etwa ein Petabyte.

Architektur der Speicherung und Ausgabe von Fotos in Badoo

Mit dem Wachstum des Datensatzes sind auch die Betriebskosten erheblich gestiegen. Inwieweit äußerte sich das?

Architektur der Speicherung und Ausgabe von Fotos in Badoo

In diesem Schema, das gezeichnet ist – mit SAN, den angeschlossenen Maschinen und Caches – gibt es viele Fehlerpunkte. Während wir mit dem Ausfall der Cache-Server, den wir bereits bewältigt haben, recht gut klargekommen sind, war es auf der Seite des Storages viel schlimmer.

Zunächst einmal kann selbst das Storage Area Network (SAN) ausfallen.

Außerdem ist es über Glasfaser mit den Endmaschinen verbunden. Es kann Probleme mit den optischen Karten oder Switches geben.

Architektur der Speicherung und Ausgabe von Fotos in Badoo

Diese sind zwar nicht so zahlreich wie beim SAN selbst, aber dennoch sind sie auch Punkte, an denen Ausfälle auftreten können.

Darüber hinaus die Maschine selbst, die mit dem Storage verbunden ist. Sie kann ebenfalls ausfallen.

Architektur der Speicherung und Ausgabe von Fotos in Badoo

Insgesamt haben wir also drei Fehlerpunkte.

Zusätzlich zu den Fehlerpunkten ist der Wartungsaufwand der Storages hoch.

Es handelt sich um ein komplexes, mehrkomponentiges System, und es kann für Systemtechniker schwierig sein, damit umzugehen.

Und der letzte, der wichtigste Punkt. Wenn an einem dieser drei Punkte ein Ausfall auftritt, haben wir eine nicht zu vernachlässigende Wahrscheinlichkeit, dass Benutzerdaten verloren gehen, da das Dateisystem beschädigt werden kann.

Architektur der Speicherung und Ausgabe von Fotos in Badoo

Angenommen, unser Dateisystem ist beschädigt. Die Wiederherstellung dauert erstens lange – das kann bei einer großen Datenmenge eine Woche in Anspruch nehmen. Und zweitens erhalten wir wahrscheinlich eine Menge unverständlicher Dateien, die wir irgendwie mit den Fotos der Benutzer abgleichen müssen. Und wir riskieren, Daten zu verlieren. Das Risiko ist ziemlich hoch. Je häufiger solche Situationen auftreten und je mehr Probleme in dieser gesamten Kette entstehen, desto höher ist dieses Risiko.

Damit mussten wir etwas unternehmen. Und wir haben beschlossen, einfach die Daten zu sichern. Das ist tatsächlich eine naheliegende und gute Lösung. Was haben wir gemacht?

Architektur der Speicherung und Ausgabe von Fotos in Badoo

So sah unser Server aus, der früher mit dem Storage verbunden war. Das ist eine Hauptpartition, ein einfaches Blockgerät, das tatsächlich ein Mount auf den entfernten Storage über Glasfaser darstellt.

Wir haben einfach eine zweite Partition hinzugefügt.

Architektur der Speicherung und Ausgabe von Fotos in Badoo

Wir haben einen zweiten Storage daneben installiert (zum Glück ist das finanziell nicht so teuer) und ihn Backup-Bereich genannt. Er ist ebenfalls über Glasfaser verbunden und befindet sich auf demselben Server. Aber wir müssen die Daten irgendwie zwischen ihnen synchronisieren.

Hier richten wir einfach eine asynchrone Warteschlange daneben ein.

Architektur der Speicherung und Ausgabe von Fotos in Badoo

Sie ist nicht sehr stark ausgelastet. Wir wissen, dass wir wenig Einträge haben. Die Warteschlange ist einfach eine Tabelle in MySQL, in die Zeilen eingefügt werden wie "Wir müssen dieses Foto sichern". Bei jeder Änderung oder beim Upload kopieren wir asynchron oder einfach mit einem Background Worker vom Hauptbereich auf das Backup.

So haben wir immer zwei konsistente Bereiche. Selbst wenn ein Teil dieses Systems ausfällt, können wir den Hauptbereich mit dem Backup austauschen und alles funktioniert weiter.

Aber dadurch steigt die Leselast stark, da neben den Clients, die vom Hauptbereich lesen, weil sie sich die Fotos dort zuerst ansehen (sie sind dort frischer), und dann auf dem Backup suchen, falls sie nichts finden (aber das erledigt einfach NGINX), auch unser Backup-System nun vom Hauptbereich liest. Es ist nicht so, dass das der Engpass wäre, aber ich wollte die Last nicht einfach so erhöhen.

Und wir haben eine dritte Festplatte hinzugefügt, die ein kleiner SSD ist und als Puffer bezeichnet wird.

Architektur der Speicherung und Ausgabe von Fotos in Badoo

Wie funktioniert das jetzt?

Der Benutzer lädt ein Foto auf den Puffer hoch, woraufhin ein Ereignis in die Warteschlange geworfen wird, dass es auf zwei Bereiche kopiert werden muss. Es wird kopiert, und das Foto bleibt eine Zeit lang (sagen wir, einen Tag) im Puffer, bevor es gelöscht wird. Das verbessert die Benutzererfahrung erheblich, denn der Benutzer lädt das Foto normalerweise hoch und erhält sofort Anfragen, oder er aktualisiert die Seite, refresht. Aber das hängt alles von der Anwendung ab, die den Upload durchführt.

Oder zum Beispiel senden andere Menschen, die es sehen, direkt nach diesem Foto Anfragen. Im Cache ist es noch nicht, die erste Anfrage erfolgt sehr schnell. Im Grunde genommen ist es dasselbe wie beim Foto-Cache. Der langsame Storage ist daran überhaupt nicht beteiligt. Wenn es nach einem Tag gelöscht wird, ist es entweder bereits in unserer Caching-Schicht zwischengespeichert oder es wird wahrscheinlich niemand mehr benötigt. Das heißt, die Benutzererfahrung hat dank solcher einfachen Manipulationen enorm zugenommen.

Und das Wichtigste: Wir haben aufgehört, Daten zu verlieren.

Architektur der Speicherung und Ausgabe von Fotos in Badoo

Wir haben sozusagen aufgehört. potenziell Daten zu verlieren, weil wir sie eigentlich nicht wirklich verloren haben. Aber die Gefahr war da. Wir sehen, dass diese Lösung natürlich gut ist, aber sie ähnelt ein wenig dem Glätten der Symptome des Problems, anstatt es vollständig zu lösen. Und einige Probleme sind hier geblieben.

Erstens ist das ein Ausfallpunkt, nämlich der physikalische Host, auf dem all diese Maschine läuft; dieser ist nicht verschwunden.

Architektur der Speicherung und Ausgabe von Fotos in Badoo

Zweitens bleiben Probleme mit den SANs, ihre schwierige Wartung usw. Es war nicht unbedingt ein kritischer Faktor, aber wir wollten versuchen, wie es wäre, ohne sie zu leben.

Wir haben die dritte Version (im Grunde genommen die zweite) – die Version der Reservierung gemacht. Wie sah das aus?

Das war, was war –

Architektur der Speicherung und Ausgabe von Fotos in Badoo

Unsere Hauptprobleme liegen darin, dass es sich um einen physikalischen Host handelt.

Erstens entfernen wir die SANs, weil wir experimentieren und einfach nur lokale Festplatten ausprobieren wollen.

Architektur der Speicherung und Ausgabe von Fotos in Badoo

Es war bereits 2014-2015, und zu diesem Zeitpunkt hat sich die Situation mit Festplatten und deren Kapazität in einem Host erheblich verbessert. Wir dachten, warum nicht ausprobieren.

Anschließend nehmen wir einfach unsere Backup-Partition und übertragen sie physisch auf eine separate Maschine.

Architektur der Speicherung und Ausgabe von Fotos in Badoo

So ergeben sich folgende Struktur. Wir haben zwei Maschinen, die identische Datensätze speichern. Sie sichern sich gegenseitig vollständig und synchronisieren die Daten über das Netzwerk mithilfe einer asynchronen Warteschlange im selben MySQL.

Architektur der Speicherung und Ausgabe von Fotos in Badoo

Warum das gut funktioniert – weil wir wenige Schreibvorgänge haben. Das heißt, wenn die Schreibvorgänge mit den Lesevorgängen vergleichbar wären, würden wir möglicherweise einen gewissen Netzwerk-Overhead und Probleme haben. Wenige Schreibvorgänge, viele Lesevorgänge – diese Methode funktioniert gut, das heißt, wir kopieren ziemlich selten Fotos zwischen diesen beiden Servern.

Wie das funktioniert, wenn man etwas detaillierter hinschaut.

Architektur der Speicherung und Ausgabe von Fotos in Badoo

Upload. Der Load-Balancer wählt einfach zufällig Hosts aus und führt den Upload auf ihm durch. Dabei führt er natürlich Gesundheitschecks durch und sorgt dafür, dass die Maschine nicht ausfällt. Das heißt, er lädt Fotos nur auf einen aktiven Server hoch, und anschließend wird alles über die asynchrone Warteschlange auf seinen Nachbarn kopiert. Mit dem Upload ist alles ganz einfach.

Mit der Aufgabe ist es ein bisschen komplizierter.

Architektur der Speicherung und Ausgabe von Fotos in Badoo

Hier hat uns Lua geholfen, weil es mit Vanilla NGINX schwierig ist, eine solche Logik umzusetzen. Zunächst machen wir eine Anfrage an den ersten Server und prüfen, ob das Foto dort vorhanden ist, da es möglicherweise zum Nachbarn hochgeladen wurde und hier noch nicht angekommen ist. Wenn das Foto vorhanden ist, ist das gut. Wir geben es sofort an den Kunden weiter und speichern es möglicherweise im Cache.

Architektur der Speicherung und Ausgabe von Fotos in Badoo

Wenn es nicht vorhanden ist, stellen wir einfach eine Anfrage an den Nachbarn und erhalten es garantiert von dort.

Architektur der Speicherung und Ausgabe von Fotos in Badoo

So kann man wieder sagen: Es können Performance-Probleme auftreten, da ständige Round Trips – das Foto wurde hochgeladen, hier ist es nicht, wir machen zwei Anfragen statt einer – langsam funktionieren sollten.

In unserer Situation funktioniert es jedoch nicht langsam.

Architektur der Speicherung und Ausgabe von Fotos in Badoo

Wir sammeln viele Metriken zu diesem System, und die bedingte Trefferquote dieses Mechanismus liegt bei etwa 95 %. Das heißt, die Verzögerung dieses Backups ist gering, und dadurch können wir praktisch garantiert, nachdem das Foto hochgeladen wurde, es beim ersten Mal abholen und müssen nirgends zweimal hin.

Was haben wir also noch erhalten, und was ist sehr cool?

Früher hatten wir einen Haupt-Backup-Bereich, und wir haben sequenziell von dort gelesen. Das heißt, wir haben immer zuerst auf dem Haupt-Backup gesucht und dann auf dem Backup. Das war ein Durchlauf.

Jetzt nutzen wir das Lesen von zwei Maschinen gleichzeitig. Wir verteilen die Anfragen round robin. In einem kleinen Prozentsatz der Fälle machen wir zwei Anfragen. Aber insgesamt haben wir jetzt eine doppelt so große Lesekapazität wie früher. Und die Last hat sich sowohl auf den abgebenden Maschinen als auch auf den Speichermedien, die wir damals auch hatten, deutlich reduziert.

Was die Ausfallsicherheit betrifft. Dafür haben wir hauptsächlich gekämpft. Bei der Ausfallsicherheit lief hier alles großartig.

Architektur der Speicherung und Ausgabe von Fotos in Badoo

Eine Maschine fällt aus.

Architektur der Speicherung und Ausgabe von Fotos in Badoo

Kein Problem! Der Systemingenieur kann sogar nachts schlafen, er wartet bis zum Morgen, es wird nichts Schlimmes passieren.

Selbst wenn bei einem Ausfall dieser Maschine die Warteschlange ausgefallen ist, gibt es auch keine Probleme; einfach wird das Protokoll zuerst auf der funktionierenden Maschine gesammelt und dann geht es in die Warteschlange, und anschließend auf die Maschine, die nach einer gewissen Zeit wieder in Betrieb genommen wird.

Architektur der Speicherung und Ausgabe von Fotos in Badoo

Das Gleiche gilt für das Maintenance. Wir schalten einfach eine der Maschinen aus, ziehen sie manuell aus allen Pools, ihr Traffic stoppt, wir führen ein gewisses Maintenance durch, ändern etwas, und danach bringen wir sie wieder in den Betrieb. Dieses Backup holt schnell auf. Das heißt, ein Ausfall von einem Tag wird innerhalb von wenigen Minuten aufgeholt. Das ist wirklich sehr wenig. Mit der Ausfallsicherheit, muss ich sagen, ist hier alles großartig.

Welche Schlussfolgerungen können wir aus diesem Schema der Redundanz ziehen?

Wir haben Ausfallsicherheit erreicht.

Einfache Bedienung. Da die Maschinen lokale Festplatten haben, ist das aus Sicht der Ingenieure, die damit arbeiten, viel bequemer.

Wir haben einen doppelten Puffer beim Lesen erhalten.

Das ist ein sehr guter Bonus zur Ausfallsicherheit.

Aber es gibt auch Probleme. Jetzt ist die Entwicklung gewisser Funktionen damit viel komplexer, weil das System zu 100 % eventually consistent geworden ist.

Architektur der Speicherung und Ausgabe von Fotos in Badoo

Wir müssen zum Beispiel in einem Hintergrundjob ständig überlegen: „Auf welchem Server sind wir gerade aktiv?“, „Gibt es hier wirklich ein aktuelles Bild?“ usw. Das ist natürlich alles in Wrappern eingekapselt, und für den Programmierer, der die Geschäftslogik schreibt, ist es transparent. Dennoch ist dies eine große komplexe Schicht entstanden. Aber wir sind bereit, damit zu leben, im Austausch gegen die Vorteile, die wir dadurch erhalten haben.

Und hier entsteht wieder ein gewisser Konflikt.

Ich habe zu Beginn gesagt, dass es schlecht ist, alles auf lokalen Festplatten zu speichern. Und jetzt sage ich, dass es uns gefallen hat.

Ja, tatsächlich hat sich die Situation im Laufe der Zeit stark verändert, und dieser Ansatz hat nun viele Vorteile. Erstens erhalten wir eine viel einfachere Bedienung.

Zweitens ist es effizienter, da wir diese automatischen Controller und Verbindungen zu den Disk-Arrays nicht haben.

Dort gibt es eine riesige Maschinenlandschaft, hier handelt es sich nur um einige Platten, die konkret hier im RAID auf der Maschine zusammengeschaltet sind.

Aber es gibt auch Nachteile.

Architektur der Speicherung und Ausgabe von Fotos in Badoo

Es ist ungefähr 1,5-mal teurer als die Nutzung von SANs, selbst zu den heutigen Preisen. Deshalb haben wir uns entschieden, nicht so kühn zu sein und unser ganzes großes Cluster in Maschinen mit lokalen Festplatten zu konvertieren und haben uns für eine hybride Lösung entschieden.

Die Hälfte unserer Maschinen arbeitet mit Festplatten (naja, nicht die Hälfte – vielleicht 30 Prozent). Der Rest sind alte Geräte, auf denen früher das erste Backup-System lief. Wir haben sie einfach umkonfiguriert, da wir weder neue Daten noch etwas anderes brauchen, sondern einfach die Mounts von einem physischen Host auf zwei umgestellt haben.

Wir haben nun einen großen Puffer beim Lesen, und wir haben uns vergrößert. Früher haben wir jeweils einen Storage auf eine Maschine montiert, jetzt montieren wir auf ein Paar vier, zum Beispiel. Und das funktioniert gut.

Lassen Sie uns eine kurze Zusammenfassung dessen geben, was wir erreicht haben, worum wir gekämpft haben und ob es geklappt hat.

Ergebnisse

Wir haben 33 Millionen Benutzer.

Wir haben drei Standorte – Prag, Miami, Hongkong.

Dort haben wir eine Cache-Schicht, die aus Maschinen mit schnellen lokalen Festplatten (SSD) besteht, auf denen eine einfache Maschine aus NGINX, dessen access.log und Daemonen in Python arbeitet, die alles verarbeiten und den Cache verwalten.

Wenn Sie in Ihrem Projekt möchten, dass Fotos nicht so kritisch sind wie für uns, oder wenn der Trade-off zwischen Kontrolle und Entwicklungs- sowie Ressourcenkosten auf Ihrer Seite eher zu Gunsten der Geschwindigkeit geht, können Sie es problemlos durch ein CDN ersetzen; moderne CDNs machen das gut.

Dann kommt die Speicherschicht, auf der Cluster von Maschinenpärchen angeordnet sind, die sich gegenseitig sichern, wobei Dateien bei Änderungen asynchron von einer auf die andere kopiert werden.

Einige dieser Maschinen arbeiten mit lokalen Festplatten.

Einige dieser Maschinen sind mit SANs verbunden.

Architektur der Speicherung und Ausgabe von Fotos in Badoo

Und auf der einen Seite ist es in der Bedienung bequemer und etwas leistungsfähiger, auf der anderen Seite ist es aus Sicht der Dichte und der Kosten pro Gigabyte praktisch.

Das ist eine kurze Übersicht über die Architektur dessen, was wir erhalten haben und wie es sich entwickelt hat.

Noch ein paar ganz einfache Tipps vom Chef.

Erstens, wenn Sie plötzlich entscheiden, dass Sie dringend alles in Ihrer Foto-Infrastruktur verbessern müssen, messen Sie zuerst, denn möglicherweise gibt es nichts zu verbessern.

Architektur der Speicherung und Ausgabe von Fotos in Badoo

Ich gebe ein Beispiel. Wir haben einen Cluster von Maschinen, der Fotos aus Anhängen in Chats bereitstellt, und dort läuft immer noch das System aus dem Jahr 2009, und niemand leidet darunter. Alle sind zufrieden, alle finden es gut.

Um zu messen, hängen Sie zunächst eine Reihe von Metriken auf, schauen Sie sich diese an und entscheiden Sie dann, was Ihnen nicht gefällt und was verbessert werden muss. Um das zu messen, haben wir ein großartiges Tool namens Pinba.

Es ermöglicht, sehr detaillierte Statistiken von NGINX für jede Anfrage, die Antwortcodes und Zeitverteilungen zu sammeln – alles, was man will. Es gibt Bindings für verschiedene Analysesysteme, sodass Sie alles schön anzeigen können.

Zuerst gemessen – dann verbessert.

Weiter. Wir optimieren das Lesen mit Caching, das Schreiben – mit Sharding, aber das ist offensichtlich.

Architektur der Speicherung und Ausgabe von Fotos in Badoo

Weiter. Wenn Sie gerade erst anfangen, Ihr System aufzubauen, ist es viel besser, Bilder als unveränderliche Dateien zu speichern. Auf diese Weise vermeiden Sie gleich einen ganzen Klassensatz an Problemen mit Cache-Invalidierung und der Frage, wie die Logik die richtige Version des Bildes finden soll.

Architektur der Speicherung und Ausgabe von Fotos in Badoo

Angenommen, Sie haben ein Hundert hochgeladen, dann haben Sie es gedreht, sorgen Sie dafür, dass es eine physisch andere Datei ist. Das heißt, Sie müssen nicht denken: Jetzt spare ich ein bisschen Platz, ich speichere in derselben Datei, ändere die Version. Das funktioniert immer schlecht und führt später zu vielen Kopfschmerzen.

Nächster Punkt. Über das Resize in Echtzeit.

Früher, als Benutzer ein Foto hochluden, haben wir sofort eine ganze Menge Größen für alle Lebenslagen für verschiedene Clients erstellt, und alle lagen auf der Festplatte. Jetzt haben wir das eingestellt.

Wir haben nur drei Hauptgrößen behalten: klein, mittel und groß. Alles andere skalieren wir einfach von der Größe, die hinter der angeforderten Größe steht, in Uport herab, einfach Downsizing und dem Benutzer geben.

Der CPU-Caching-Schicht ist hier viel günstiger, als wenn wir diese Größen auf jedem Storage ständig neu generieren würden. Angenommen, wir möchten eine neue hinzufügen, es dauert einen Monat – ein Skript überall laufen zu lassen, das alles ordentlich macht, ohne den Cluster zu überlasten. Das heißt, wenn es jetzt die Möglichkeit gibt, sollte man möglichst wenige physische Größen erstellen, aber um eine gewisse Verteilung zu haben, sagen wir drei. Und alles andere einfach in Echtzeit mithilfe fertiger Module skalieren. Das ist jetzt alles sehr einfach und zugänglich.

Und inkrementelles, asynchrones Backup ist gut.

Wie unsere Praxis gezeigt hat, funktioniert ein solches Schema sehr gut mit der verzögerten Kopie geänderter Dateien.

Architektur der Speicherung und Ausgabe von Fotos in Badoo

Der letzte Punkt ist ebenfalls offensichtlich. Wenn es in Ihrer Infrastruktur derzeit keine solchen Probleme gibt, aber etwas vorhanden ist, das ausfallen könnte, wird es definitiv dann ausfallen, wenn es etwas mehr wird. Daher ist es besser, sich im Voraus Gedanken darüber zu machen und dabei keine Probleme zu haben. Ich habe alles.

Kontakte

» bo0rsh201
» Blog des Unternehmens Badoo

Dieser Vortrag ist eine Transkription eines der besten Vorträge auf der Konferenz für Entwickler hochbelasteter Systeme. HighLoad++. Bis zur Konferenz HighLoad++ 2017 sind es weniger als einen Monat.

Wir sind bereits bereit, Konferenzprogrammdas Programm wird gerade aktiv erstellt.

In diesem Jahr setzen wir unsere Erkundung des Themas Architekturen und Skalierung fort:

Einige dieser Materialien verwenden wir auch in unserem Online-Kurs zur Entwicklung hochbelasteter Systeme. HighLoad.Guide ist eine Reihe von speziell ausgewählten E-Mails, Artikeln, Materialien und Videos. In unserem Lehrbuch befinden sich bereits über 30 einzigartige Materialien. Machen Sie mit!

Quelle: habr.com

60GB SSD 8Gb DDR4