Architektur zur Speicherung und Auslieferung von Fotos in Badoo

Architektur zur Speicherung und Auslieferung von Fotos in Badoo

Artem Denisov ( bo0rsh201, Badoo)

Badoo ist die größte Dating-Website der Welt. Derzeit haben wir etwa 330 Millionen registrierte Nutzer weltweit. Aber was in unserem heutigen Gespräch viel wichtiger ist, ist, dass wir rund 3 Petabyte an Benutzerfotos speichern. Täglich laden unsere Nutzer etwa 3,5 Millionen neue Fotos hoch, und die Leseanfragen belaufen sich auf ungefähr 80.000 Anfragen pro Sekunde. Das ist ziemlich anspruchsvoll für unser Backend, und manchmal gibt es dabei Schwierigkeiten.

Architektur zur Speicherung und Auslieferung von Fotos in Badoo

Ich werde über das Design dieses Systems sprechen, das Fotos speichert und bereitstellt, und ich gebe einen Entwicklerblick darauf. Ich werde kurz die Entwicklung beleuchten und die wichtigsten Meilensteine ansprechen, aber ausführlicher über die Lösungen sprechen, die wir derzeit verwenden.

Und jetzt lassen Sie uns beginnen.

Video abspielen

Wie ich bereits sagte, wird dies eine Rückschau sein, und um damit zu beginnen, nehmen wir das naheliegendste Beispiel.

Architektur zur Speicherung und Auslieferung von Fotos in Badoo

Wir haben eine allgemeine Aufgabe, wir müssen Fotos der Nutzer empfangen, speichern und bereitstellen. In diesem allgemeinen Kontext können wir alles verwenden:

  • modernen Cloud-Speicher,
  • eine Box-Lösung, von denen es jetzt auch viele gibt;
  • wir können mehrere Maschinen in unserem Rechenzentrum einrichten, große Festplatten installieren und die Fotos dort speichern.

Badoo lebt historisch — und das gilt sowohl jetzt als auch damals, als es gerade anfing — auf eigenen Servern in unseren eigenen Rechenzentren. Daher war diese Option für uns optimal.

Architektur zur Speicherung und Auslieferung von Fotos in Badoo

Wir haben einfach ein paar Maschinen genommen, sie 'photos' genannt, und so einen Cluster aufgebaut, der die Fotos speichert. Aber es scheint, dass etwas fehlt. Um das alles funktionsfähig zu machen, müssen wir irgendwie bestimmen, auf welcher Maschine welche Fotos gespeichert werden. Hier muss man keine neue Wahrheit entdecken.

Architektur zur Speicherung und Auslieferung von Fotos in Badoo

Wir fügen unserem Speicher eine Information über die Nutzer hinzu, ein Feld. Dies wird der Sharding-Schlüssel sein. In unserem Fall haben wir es place_id genannt, und dieser Ort-ID zeigt auf den Speicherort der Benutzerfotos. Wir erstellen Karten.

In der ersten Phase kann das sogar manuell gemacht werden — wir sagen, dass das Foto dieses Nutzers mit diesem Ort auf diesen Server gespeichert wird. Dank dieser Karte wissen wir immer, wo das Foto gespeichert werden soll, sobald der Nutzer es hochlädt, und kennen auch den Ort, von dem es bereitgestellt werden soll.

Das ist ein absolut triviales Schema, aber es bietet einige wesentliche Vorteile. Erstens ist es, wie ich bereits erwähnte, einfach, und zweitens — mit diesem Ansatz können wir einfach horizontal skalieren, indem wir neue Maschinen hinzufügen und sie in die Karte einfügen. Mehr muss nicht getan werden.

So war es eine Zeit lang bei uns.

Architektur zur Speicherung und Auslieferung von Fotos in Badoo

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

Und irgendwann begannen wir zu bemerken, dass dieses Schema bestimmte Nachteile hat. Welche Nachteile?

In erster Linie ist es die begrenzte Kapazität. Wir können auf einem physischen Server nicht so viele Festplatten unterbringen, wie wir es gerne hätten. Und das wurde im Laufe der Zeit und mit der steigenden Datenmenge zu einem Problem.

Und zweitens. Es handelt sich um eine atypische Maschinenkonfiguration, da solche Maschinen schwer in anderen Clustern wiederverwendet werden können; sie sind ziemlich spezifisch, d.h. sie müssen in der Leistung schwach sein, aber gleichzeitig große Festplatten haben.

Das alles war im Jahr 2009, aber im Grunde sind diese Anforderungen auch heute noch relevant. Da wir eine Retrospektive haben, war es 2009 damit sehr schlecht.

Und der letzte Punkt — die Kosten.

Architektur zur Speicherung und Auslieferung von Fotos in Badoo

Die Kosten waren damals sehr hoch, und wir mussten nach Alternativen suchen. Das heißt, wir mussten sehen, wie wir sowohl den Platz in den Rechenzentren als auch die physischen Server, auf denen alles untergebracht ist, besser nutzen können. Unsere Systemingenieure haben eine große Studie gemacht, in der sie viele verschiedene Optionen überprüft haben. Sie haben sich auch Cluster-Dateisystemen wie PolyCeph und Lustre angesehen. Dort gab es Leistungsprobleme und eine ziemlich schwere Nutzung. Davon wurden sie abgebracht. Sie haben versucht, den gesamten Datensatz über NFS auf jede Maschine zu mounten, um so irgendwie zu skalieren. Das Lesen war auch nicht ideal, sie haben verschiedene Lösungen von verschiedenen Anbietern ausprobiert.

Und schließlich haben wir uns entschieden, das sogenannte Storage Area Network zu verwenden.

Architektur zur Speicherung und Auslieferung von Fotos in Badoo

Das sind große SHDs, die speziell für die Speicherung großer Datenmengen ausgelegt sind. 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, die für unsere Auslieferungslogik, wie zum Beispiel nginx oder anderen, transparent sind, bedienen die Anfragen nach diesen Fotos.

Diese Lösung brachte offensichtliche Vorteile mit sich. Es handelt sich um SHDs, die auf die Speicherung von Fotos ausgerichtet sind. Es ist günstiger, als wenn wir Maschinen mit Festplatten einrichten.

Ein weiterer Vorteil.

Architektur zur Speicherung und Auslieferung von Fotos in Badoo

Die Kapazität ist erheblich gestiegen, das heißt, wir können in deutlich kleinerem Umfang viel mehr Speicherplatz unterbringen.

Aber es gab auch Nachteile, die sich schnell zeigten. Mit der steigenden Anzahl von Nutzern und der Belastung des Systems traten Leistungsprobleme auf. Das Problem ist offensichtlich – jede SHD, die dafür gedacht ist, viele Fotos auf engem Raum zu speichern, leidet in der Regel unter intensiven Lesevorgängen. Dies ist tatsächlich auch für jeden Cloud-Speicher relevant. Gegenwärtig gibt es kein ideales Speichergerät, das unbegrenzt skalierbar ist, in das man alles Mögliche stecken kann und das gleichzeitig gut mit Lesevorgängen umgehen kann, insbesondere mit zufälligen Lesevorgängen.

Architektur zur Speicherung und Auslieferung von Fotos in Badoo

Wie im Fall unserer Fotos, da diese unregelmäßig angefragt werden, was die Leistung erheblich beeinflusst.

Schon nach heutigen Zahlen, wenn bei uns mehr als 500 RPS pro Maschine mit Speicher ausfallen, entstehen bereits Probleme. Und das war für uns problematisch, da die Anzahl der Nutzer wächst und alles nur schlimmer werden sollte. Wir müssen das irgendwie optimieren.

Um zu optimieren, haben wir damals offensichtlicherweise beschlossen, das Lastprofil zu betrachten – was passiert, was optimiert werden muss.

Architektur zur Speicherung und Auslieferung von Fotos in Badoo

Und hier spielen uns alle Faktoren in die Karten.

Ich habe bereits auf der ersten Folie erwähnt: Wir haben 80.000 Leseanfragen pro Sekunde bei nur 3,5 Millionen Uploads pro Tag. Das ist eine Differenz von drei Größenordnungen. Offensichtlich muss das Lesen optimiert werden und es ist nahezu klar, wie.

Es gibt noch einen kleinen Punkt. Die Spezifik des Services besteht darin, dass sich ein Nutzer registriert, ein Foto hochlädt, danach aktiv die Fotos anderer Nutzer ansieht, sie liked und aktiv anderen Nutzern angezeigt wird. Dann findet er einen Partner oder nicht, das kommt darauf an, und hört für eine Weile auf, den Service zu nutzen. In dem Moment, in dem er aktiv ist, sind seine Fotos sehr gefragt – sie werden von vielen Nutzern angesehen. Sobald er damit aufhört, fällt er schnell aus den intensiven Anzeigen, wie vorher, heraus, und seine Fotos werden praktisch nicht mehr angefragt.

Architektur zur Speicherung und Auslieferung von Fotos in Badoo

Das heißt, wir haben einen sehr kleinen heißen Datensatz. Aber dafür gibt es viele Anfragen. Eine offensichtliche Lösung besteht darin, einen Cache hinzuzufügen.

Ein LRU-Cache wird all unsere Probleme lösen. Was tun wir?

Architektur zur Speicherung und Auslieferung von Fotos in Badoo

Wir fügen vor unserem großen Speichercluster noch einen vergleichsweise kleinen hinzu, den wir Fotokäse (photoscache) nennen. Das ist im Grunde ein Proxy, der die Daten cached.

Wie funktioniert das intern? Hier ist unser Nutzer, hier ist der Speicher. Alles wie zuvor. Was fügen wir zwischen ihnen hinzu?

Architektur zur Speicherung und Auslieferung von Fotos in Badoo

Das ist einfach eine Maschine mit einer schnellen lokalen Festplatte, zum Beispiel SSD. Auf dieser Festplatte befindet sich ein lokaler Cache.

Wie sieht das aus? Der Nutzer sendet eine Anfrage nach einem Foto. NGINX sucht zuerst im lokalen Cache. Falls nicht vorhanden, macht es einfach einen proxy_pass zu unserem Speicher, lädt das Foto von dort herunter und gibt es dem Nutzer.

Das klingt sehr einfach und es ist nicht klar, was intern passiert. Es funktioniert ungefähr so.

Architektur zur Speicherung und Auslieferung von Fotos in Badoo

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

  1. Ein Puffer, wohin gerade aus dem Proxy geladene Fotos gelangen.
  2. Ein heißer Cache, in dem aktiv angeforderte Fotos gespeichert werden.
  3. Und ein kalter Cache, wo Fotos nach und nach aus dem heißen Cache gedrängt werden, wenn weniger Anfragen eingehen.

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

Architektur zur Speicherung und Auslieferung von Fotos in Badoo

Nginx schreibt bei jedem Request einfach in access.log auf RAMDisk, wo der Pfad zum Bild angegeben ist, das gerade bedient wird (natürlich relativer Pfad), und welcher Abschnitt dafür zuständig war. Das heißt, dort könnte stehen „Foto 1“ und danach entweder Puffer, heißer Cache, kalter Cache oder Proxy.

Je nachdem müssen wir eine Entscheidung treffen, was wir mit dem Bild machen.

Auf jeder Maschine läuft ein kleiner Daemon, der ständig dieses Log ausliest und in seinem Speicher eine Statistik über die Nutzung bestimmter Fotos speichert.

Architektur zur Speicherung und Auslieferung von Fotos in Badoo

Er sammelt einfach die Daten, führt Zählungen und macht dann regelmäßig Folgendes: Aktive Fotos, für die viele Requests kommen, verschiebt er in den heißen Cache, egal wo sie sich gerade befinden.

Architektur zur Speicherung und Auslieferung von Fotos in Badoo

Fotos, die selten angefordert werden und deren Anfragen zurückgehen, schiebt er allmählich aus dem heißen Cache in den kalten.

Architektur zur Speicherung und Auslieferung von Fotos in Badoo

Und wenn der Platz in unserem Cache eng wird, beginnen wir einfach, alles ohne Unterscheidung aus dem kalten Cache zu löschen. Und das funktioniert übrigens ganz gut.

Um sicherzustellen, dass das Foto sofort beim Proxying in den Puffer gespeichert wird, verwenden wir die Direktive proxy_store, und der Puffer ist ebenfalls RAMDisk, d.h. für den Nutzer funktioniert das sehr schnell. Das betrifft die interne Struktur des Cache-Servers.

Die Frage bleibt, wie wir die Requests auf diese Server verteilen.

Nehmen wir an, es gibt ein Cluster aus zwanzig Storage-Maschinen und drei Cache-Server (so hat es sich ergeben).

Architektur zur Speicherung und Auslieferung von Fotos in Badoo

Wir müssen irgendwie bestimmen, welche Requests für welche Fotos wo hin geleitet werden.

Die einfachste Variante ist Round Robin. Oder zufällig zu entscheiden?

Das hat offenbar eine Reihe von Nachteilen, da wir in so einer Situation den Cache sehr ineffizient nutzen würden. Anfragen würden auf irgendwelche zufälligen Maschinen fallen: hier wurde sie gecached, auf der benachbarten ist sie schon nicht mehr vorhanden. Und wenn es funktioniert, dann sehr schlecht. Selbst bei einer geringen Anzahl von Maschinen im Cluster.

Wir müssen eindeutig bestimmen, auf welchen Server welcher Request geleitet werden soll.

Es gibt einen einfachen Weg. Wir nehmen den Hash der URL oder den Hash unseres Sharding-Schlüssels, der in der URL enthalten ist, und teilen diesen durch die Anzahl der Server. Wird das funktionieren? Ja.

Architektur zur Speicherung und Auslieferung von Fotos in Badoo

Das bedeutet, unser hundertprozentiger Request, zum Beispiel für irgendeine „example_url“, wird immer auf den Server mit dem Index „2“ geleitet, und der Cache wird konstant optimal genutzt.

Aber in solch einem Schema entsteht ein Problem mit dem Resharding. Mit Resharding meine ich die Änderung der Anzahl von Servern.

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

Wir fügen sie hinzu.

Architektur zur Speicherung und Auslieferung von Fotos in Badoo

Jetzt teilen wir nicht mehr durch drei, sondern durch vier. Somit wohnen praktisch alle Schlüssel, die wir früher hatten, praktisch alle URLs nun auf anderen Servern. Der gesamte Cache wurde einfach in diesem Moment ungültig. Alle Anfragen strömten auf unser Cluster-Storage, es gab eine Überlastung und unzufriedene Nutzer. Das wollen wir nicht.

Diese Option ist uns ebenfalls nicht geeignet.

Was müssen wir also tun? Wir müssen irgendwie den Cache effizient nutzen, ständig einen Request auf denselben Server leiten und dabei resistent gegen Resharding sein. Und es gibt eine Lösung dafür, die nicht allzu kompliziert ist. Sie heißt konsistentes Hashing.

Architektur zur Speicherung und Auslieferung von Fotos in Badoo

Wie sieht das aus?

Architektur zur Speicherung und Auslieferung von Fotos in Badoo

Wir nehmen eine Funktion des Sharding-Keys und verteilen alle ihre Werte gleichmäßig auf einem Kreis. Das heißt, an Punkt 0 treffen sich ihre minimalen und maximalen Werte. Dann platzieren wir auf demselben Kreis alle unsere Server ungefähr so:

Architektur zur Speicherung und Auslieferung von Fotos in Badoo

Jeder Server wird durch einen Punkt definiert, und der Sektor, der bis zu ihm im Uhrzeigersinn geht, wird entsprechend von diesem Host bedient. Wenn uns Anfragen erreichen, sehen wir sofort, dass beispielsweise Anfrage A — hat diesen Hash — und wird von Server 2 bedient. Anfrage B — von Server 3. Und so weiter.

Architektur zur Speicherung und Auslieferung von Fotos in Badoo

Was passiert in dieser Situation beim Resharding?

Architektur zur Speicherung und Auslieferung von Fotos in Badoo

Wir invalidieren nicht den gesamten Cache wie früher und verschieben nicht alle Schlüssel, sondern schieben jeden Sektor um eine kleine Distanz, so dass unser sechster Server, den wir hinzufügen wollen, in den freigewordenen Platz passt.

Architektur zur Speicherung und Auslieferung von Fotos in Badoo

Sicher, in solch einer Situation verschieben sich auch die Schlüssel. Aber sie verschieben sich viel weniger als früher. Und wir sehen, dass unsere ersten beiden Schlüssel auf ihren Servern geblieben sind, während nur der Cache-Server für den letzten Schlüssel gewechselt hat. Das funktioniert ziemlich effektiv, und wenn Sie neue Hosts inkrementell hinzufügen, gibt es dabei kein großes Problem. Sie fügen nach und nach neue hinzu, warten, bis der Cache wieder voll ist, und alles funktioniert gut.

Die einzige Frage bleibt bei Ausfällen. Nehmen wir an, dass eine unserer Maschinen ausgefallen ist.

Architektur zur Speicherung und Auslieferung von Fotos in Badoo

Und wir möchten in diesem Moment nicht die Karte neu generieren, den Cache invalidieren usw., falls beispielsweise die Maschine neu gestartet wurde und wir die Anfragen bedienen müssen. Wir halten einfach einen Backup-Fotokache auf jedem Standort, der als Ersatz für jede Maschine dient, die derzeit ausgefallen ist. Und wenn plötzlich ein Server nicht mehr verfügbar ist, wird der Traffic dorthin geleitet. Dabei haben wir natürlich keinen Cache, d.h. er ist kalt, aber zumindest werden die Nutzeranfragen bearbeitet. Falls es nur für einen kurzen Zeitraum ist, kommen wir damit ganz gut klar. Es wird einfach mehr Last auf dem Speicher liegen. Wenn es einen langen Zeitraum betrifft, können wir die Entscheidung treffen – diesen Server von der Karte zu entfernen oder nicht, oder vielleicht ihn durch einen anderen zu ersetzen.

Das war zur Caching-System. Lassen Sie uns die Ergebnisse betrachten.

Es scheint nichts Kompliziertes dabei zu sein. Aber dieser Ansatz zur Cache-Verwaltung hat uns eine Hitrate von etwa 98 % beschert. D.h. von diesen 80.000 Anfragen pro Sekunde erreichen nur 1.600 die Speicher, und das ist eine ganz normale Last, die sie problemlos bewältigen können, wir haben immer einen Puffer.

Wir haben diese Server in drei unserer Rechenzentren platziert und erhalten drei Präsenzpunkte – Prag, Miami und Hongkong.

Architektur zur Speicherung und Auslieferung 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 tatsächlich ungenutzt ist, da sie für die Bereitstellung von Inhalten nicht so stark benötigt wird. Dort haben wir mit NGINX+ Lua viel pragmatische Logik implementiert.

Architektur zur Speicherung und Auslieferung von Fotos in Badoo

Zum Beispiel können wir mit webp oder progressive jpeg experimentieren (das sind moderne effiziente Formate), ansehen, wie sich das auf den Traffic auswirkt, Entscheidungen treffen, dies für bestimmte Länder aktivieren usw.; dynamisches Resize oder Cropping von Fotos on-the-fly durchführen.

Das ist ein guter Anwendungsfall, wenn Sie beispielsweise eine mobile Anwendung haben, die Fotos anzeigt, und die mobile Anwendung nicht die CPU des Clients für das Abrufen eines großen Fotos verwenden möchte, um es dann auf eine bestimmte Größe zu skalieren, um in die Ansicht zu passen. Wir können einfach dynamisch im URL einige Parameter im sogenannten UPort angeben, und der Fotokache wird das Bild selbst resize. In der Regel wählt er die Größe aus, die wir physisch auf der Festplatte haben und die der angeforderten möglichst nahekommt, und skaliert es an bestimmten Koordinaten herunter.

Übrigens haben wir die Videoaufzeichnungen der letzten fünf Jahre von Konferenzen über hochbelastete Systeme öffentlich zugänglich gemacht. HighLoad++. Sehen Sie sich das an, lernen Sie, teilen Sie es und abonnieren Sie den YouTube-Kanal.

Außerdem können wir dort viele produktbezogene Logik hinzufügen. Zum Beispiel können wir basierend auf den URL-Parametern unterschiedliche Wasserzeichen hinzufügen, Fotos verwischen, unscharf oder pixelieren. Das ist, wenn wir ein Foto einer Person zeigen möchten, aber nicht ihr Gesicht zeigen wollen, das funktioniert gut, all das ist hier realisiert.

Was haben wir erhalten? Wir haben drei Präsenzpunkte, eine gute Hitrate, und dabei wird die CPU dieser Maschinen nicht ungenutzt. Sie ist nun natürlich wichtiger geworden als zuvor. Wir müssen uns stärkere Maschinen anschaffen, aber das ist es wert.

Was die Bereitstellung von Fotos betrifft, ist alles ziemlich klar und offensichtlich. Ich denke, ich habe nicht Amerika entdeckt; so funktioniert praktisch jedes CDN.

Und wahrscheinlich könnte bei einem gestandenen Zuhörer die Frage aufkommen: Warum nicht einfach alles auf ein CDN umstellen? Es wäre ziemlich das Gleiche, alle modernen CDNs können das. Und hier gibt es einige Gründe.

Der erste sind die Fotos.

Architektur zur Speicherung und Auslieferung von Fotos in Badoo

Das ist einer der Schlüsselpunkte unserer Infrastruktur, und wir benötigen so viel Kontrolle wie möglich darüber. Wenn dies eine Lösung eines Drittanbieters ist und Sie keine Kontrolle darüber haben, wird es Ihnen schwer fallen, damit zu leben, wenn Sie einen großen Datensatz haben und wenn Sie einen sehr großen Strom von Benutzeranfragen haben.

Ich gebe ein Beispiel. Derzeit können wir in unserer Infrastruktur, falls es Probleme oder Erschütterungen gibt, auf die Maschine zugreifen und dort debuggen, sozusagen. Wir können spezifische Metriken erfassen, die nur für uns von Interesse sind, experimentieren und beobachten, wie sich dies auf die Grafiken auswirkt und so weiter. Momentan sammeln wir eine große Menge an Statistiken zu diesem Cache-Cluster. Wir schauen regelmäßig darauf und analysieren lange anomale Werte. Wäre dies auf der CDN-Seite, wäre es viel schwieriger zu kontrollieren. Oder zum Beispiel, wenn es zu einem Vorfall kommt, wissen wir, was passiert ist, wissen, wie wir damit leben können und wie wir es bewältigen können. Das ist die erste Erkenntnis.

Die zweite Erkenntnis ist eher historisch, weil sich das System bereits lange entwickelt, und es gab viele verschiedene Geschäftsanforderungen in verschiedenen Phasen, die nicht immer in das CDN-Konzept passten.

Und der Punkt, der sich daraus ergibt –

Architektur zur Speicherung und Auslieferung von Fotos in Badoo

Es gibt viele spezifische Logiken in unseren Fotocaches, die oft nicht auf Anfrage hinzugefügt werden können. Wahrscheinlich wird kein CDN auf Ihre Anfrage hin benutzerdefinierte Dinge hinzufügen. Zum Beispiel die Verschlüsselung von URLs, wenn Sie nicht möchten, dass Kunden etwas ändern können. Wenn Sie die URL auf dem Server ändern und sie verschlüsseln möchten, um dann einige dynamische Parameter zu übergeben.

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

Architektur zur Speicherung und Auslieferung von Fotos in Badoo

In Ihrem Fall jedoch, wenn Sie spezifische Geschäftsanforderungen haben, können Sie das, was ich Ihnen gezeigt habe, ganz entspannt selbst umsetzen. Und das wird bei ähnlichem 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 Ihnen die Zeit und Ressourcen viel wichtiger sind als die Kontrolle.

Architektur zur Speicherung und Auslieferung von Fotos in Badoo

Moderne CDNs verfügen über nahezu alles, was ich Ihnen gerade erzählt habe. Mit Ausnahme von plus minus einigen Funktionen.

Das betrifft die Auslieferung von Bildern.

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

Das Jahr 2013

Architektur zur Speicherung und Auslieferung von Fotos in Badoo

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

Architektur zur Speicherung und Auslieferung von Fotos in Badoo

Mit dem Wachstum des Datensatzes begannen die Betriebskosten erheblich zu steigen. In was äußerte sich das?

Architektur zur Speicherung und Auslieferung von Fotos in Badoo

In diesem Diagramm, das gezeichnet ist – mit SAN, mit angeschlossenen Maschinen und Caches – gibt es sehr viele Ausfallpunkte. Wenn wir früher mit den Ausfällen der Cache-Server schon umgehen konnten, da war alles mehr oder weniger vorhersehbar und verständlich, dann war es auf der Seite des Storages viel problematischer.

Einerseits kann das Storage Area Network (SAN) ausfallen.

Andererseits ist es über Glasfaser mit den Endgeräten verbunden. Es können Probleme mit den optischen Karten und Switches auftreten.

Architektur zur Speicherung und Auslieferung von Fotos in Badoo

Es sind zwar nicht so viele wie mit dem SAN selbst, aber dennoch sind auch das Ausfallpunkte.

Dann gibt es die Maschinen, die mit dem Storage verbunden sind. Auch diese können ausfallen.

Architektur zur Speicherung und Auslieferung von Fotos in Badoo

Insgesamt haben wir drei Ausfallpunkte.

Neben den Ausfallpunkten gibt es die schwierige Wartung der Speicher.

Es ist ein komplexes, mehrkomponentenes System, und es ist für Systemingenieure oft schwierig, damit umzugehen.

Und der letzte, wichtigere Punkt. Wenn an einem dieser drei Punkte ein Ausfall auftritt, haben wir eine nicht nullwahrscheinliche Gefahr, Benutzerdaten zu verlieren, weil das Dateisystem beschädigt werden kann.

Architektur zur Speicherung und Auslieferung von Fotos in Badoo

Angenommen, unser Dateisystem ist beschädigt. Die Wiederherstellung kann einerseits lange dauern – das kann bei großen Datenmengen eine Woche in Anspruch nehmen. Und andererseits werden wir wahrscheinlich eine Menge unverständlicher Dateien erhalten, die wir irgendwie den Benutzerfotos zuordnen 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 Kette entstehen, desto größer wird dieses Risiko.

Damit musste etwas unternommen werden. Und wir beschlossen, dass wir einfach die Daten sichern müssen. Das ist tatsächlich eine offensichtliche und gute Lösung. Was haben wir gemacht?

Architektur zur Speicherung und Auslieferung von Fotos in Badoo

So sah unser Server aus, der zuvor mit dem Storage verbunden war. Dies ist eine Hauptpartition, eine blockbasierte Einheit, die tatsächlich ein Mount auf den entfernten Storage über Lichtwellenleiter darstellt.

Wir haben einfach eine zweite Partition hinzugefügt.

Architektur zur Speicherung und Auslieferung von Fotos in Badoo

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

Hier erstellen wir einfach eine asynchrone Warteschlange daneben.

Architektur zur Speicherung und Auslieferung von Fotos in Badoo

Es ist nicht sehr belastet. Wir wissen, dass wir nur wenige Einträge haben. Die Warteschlange ist einfach eine Tabelle in MySQL, in die Zeilen wie „Dieses Foto muss gesichert werden“ geschrieben werden. Bei jeder Änderung oder beim Upload kopieren wir asynchron oder mit einem Hintergrundprozess vom Hauptspeicher auf das Backup.

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

Aber dadurch steigt die Leselast erheblich, denn neben den Clients, die vom Hauptspeicher lesen, weil sie sich das Foto dort zunächst ansehen (es ist ja dort aktueller), suchen sie erst auf dem Backup, wenn sie es dort nicht finden (aber das erledigt NGINX einfach). Unsere Backup-Lösung zieht nun auch Daten vom Hauptspeicher. Das ist nicht wirklich ein Engpass, aber ich wollte die Last nicht unnötig erhöhen.

Also haben wir eine dritte Festplatte hinzugefügt, einen kleinen SSD, und haben ihn als Puffer bezeichnet.

Architektur zur Speicherung und Auslieferung von Fotos in Badoo

So funktioniert das jetzt.

Der Benutzer lädt ein Foto auf den Puffer hoch, dann wird ein Event in die Warteschlange geworfen, dass es auf die beiden Speichereinheiten kopiert werden muss. Es wird kopiert, und das Foto lebt eine gewisse Zeit (sagen wir, einen Tag) im Puffer, bevor es gelöscht wird. Das verbessert das Nutzererlebnis erheblich, weil der Benutzer das Foto normalerweise hochlädt, während sofort darauf Anfragen folgen, oder er selbst die Seite aktualisiert. Aber das hängt alles von der Anwendung ab, die den Upload durchführt.

Oder, zum Beispiel, andere Personen, die das Foto sehen wollen, senden sofort Anfragen nach diesem Foto. Es ist noch nicht im Cache, die erste Anfrage passiert sehr schnell. Im Grunde genommen ist es so wie bei dem Fotocache. Der langsame Speicher ist daran nicht beteiligt. Wenn es nach einem Tag gelöscht wird, ist es entweder bereits in unserem Cache oder es wird wahrscheinlich niemand mehr benötigt. Das Nutzererlebnis hat sich durch diese einfachen Maßnahmen also erheblich verbessert.

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

Architektur zur Speicherung und Auslieferung von Fotos in Badoo

Wir haben, sagen wir mal, aufgehört potenziell Daten zu verlieren, weil wir sie nicht wirklich verloren haben. Aber die Gefahr war vorhanden. Wir sehen, dass diese Lösung natürlich gut ist, aber sie sieht etwas nach einer Symptombehandlung aus, anstatt das Problem wirklich zu lösen. Und einige Probleme bleiben noch bestehen.

Erstens gibt es den Ausfallpunkt in Form des physischen Hosts, auf dem diese ganze Infrastruktur läuft, der ist nicht verschwunden.

Architektur zur Speicherung und Auslieferung von Fotos in Badoo

Zweitens gibt es immer noch Probleme mit SANs, der schwere Wartungsaufwand usw. Das war nicht wirklich ein kritischer Faktor, aber wir wollten versuchen, ohne das auszukommen.

Also haben wir die dritte Version entwickelt (in Wirklichkeit die zweite) – die Version mit Reservierung. Wie sah das aus?

Das war es, was war –

Architektur zur Speicherung und Auslieferung von Fotos in Badoo

Unsere Hauptprobleme lagen darin, dass dies ein physischer Host war.

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

Architektur zur Speicherung und Auslieferung von Fotos in Badoo

Es war bereits 2014-2015, und zu diesem Zeitpunkt hatte sich die Situation mit Festplatten und deren Speicherkapazität pro Host erheblich verbessert. Wir dachten uns, warum nicht einfach mal ausprobieren.

Und dann nehmen wir einfach unseren Backup-Speicher und verlagern ihn physisch auf eine separate Maschine.

Architektur zur Speicherung und Auslieferung von Fotos in Badoo

So erhalten wir ein solches Schema. Wir haben zwei Maschinen, die identische Datenmengen speichern. Sie sichern sich gegenseitig vollständig und synchronisieren die Daten über das Netzwerk mittels einer asynchronen Warteschlange im gleichen MySQL.

Architektur zur Speicherung und Auslieferung von Fotos in Badoo

Warum das gut funktioniert – weil wir nur wenige Einträge haben. Wenn die Anzahl der Einträge mit der Anzahl der Lesevorgänge vergleichbar gewesen wäre, hätten wir möglicherweise eine Netzwerküberlastung und Probleme bekommen. Wenige Einträge, viele Lesevorgänge – diese Methode funktioniert gut, d.h. wir kopieren Fotos zwischen diesen beiden Servern relativ selten.

Wie funktioniert das, wenn wir es etwas detaillierter betrachten?

Architektur zur Speicherung und Auslieferung von Fotos in Badoo

Upload. Der Lastenausgleich wählt einfach zufällig Hosts aus dem Paar und führt den Upload auf ihnen durch. Dabei führt er natürlich Gesundheitschecks durch und stellt sicher, dass die Maschine nicht ausgefallen ist. D.h. er lädt Fotos nur auf den funktionierenden Server hoch, und dann wird alles über eine asynchrone Warteschlange auf den Nachbarn kopiert. Der Upload ist also ganz einfach.

Die Aufgabe ist etwas komplizierter.

Architektur zur Speicherung und Auslieferung von Fotos in Badoo

Hier hat uns Lua geholfen, denn mit Vanilla NGINX ist es manchmal schwierig, eine solche Logik umzusetzen. Wir machen zunächst eine Anfrage an den ersten Server, um zu sehen, ob das Foto dort vorhanden ist, denn es könnte theoretisch auch auf dem Nachbarserver hochgeladen worden sein und ist hier noch nicht angekommen. Wenn das Foto dort vorhanden ist, ist das gut. Wir geben es sofort an den Kunden weiter und cachen es möglicherweise.

Architektur zur Speicherung und Auslieferung von Fotos in Badoo

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

Architektur zur Speicherung und Auslieferung von Fotos in Badoo

So kann man wieder sagen: Es können Leistungsprobleme auftreten, weil ständige Round-Trips – das Foto wurde hochgeladen, aber hier ist es nicht, wir machen zwei Anfragen anstelle von einer, das sollte langsam arbeiten.

In unserer Situation funktioniert das nicht langsam.

Architektur zur Speicherung und Auslieferung von Fotos in Badoo

Wir sammeln eine Menge Metriken zu diesem System, und die bedingte Trefferquote eines solchen Mechanismus liegt bei etwa 95 %. Das heißt, die Verzögerung dieses Backups ist gering, und dadurch holen wir das Foto nahezu garantiert beim ersten Mal ab, nachdem es hochgeladen wurde, und müssen nicht zweimal nachfragen.

Was haben wir also noch erhalten, und das ist wirklich toll?

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

Jetzt nutzen wir das Lesen von zwei Maschinen gleichzeitig. Wir verteilen die Anfragen im Round-Robin-Verfahren. In einem kleinen Prozentsatz der Fälle machen wir zwei Anfragen. Aber insgesamt haben wir jetzt doppelt so viel Lesepuffer wie zuvor. Und die Belastung ist deutlich gesunken, sowohl auf den ausgebenden Maschinen als auch direkt auf den Speichern, die wir zu diesem Zeitpunkt ebenfalls hatten.

Was die Fehlertoleranz angeht: Genau dafür haben wir hauptsächlich gekämpft. Mit der Fehlertoleranz läuft hier alles hervorragend.

Architektur zur Speicherung und Auslieferung von Fotos in Badoo

Eine Maschine fällt aus.

Architektur zur Speicherung und Auslieferung von Fotos in Badoo

Keine Probleme! Der Systemingenieur muss nicht einmal nachts aufwachen, er kann bis zum Morgen warten, es wird nichts Schlimmes passieren.

Selbst wenn die Warteschlange bei einem Ausfall dieser Maschine nicht mehr funktioniert, gibt es keine Probleme, das Protokoll wird einfach zunächst auf der funktionierenden Maschine angesammelt und später in die Warteschlange überführt, und dann an die Maschine, die nach einiger Zeit wieder in Betrieb genommen wird.

Architektur zur Speicherung und Auslieferung von Fotos in Badoo

Das Gleiche gilt für Wartungsarbeiten. Wir schalten einfach eine der Maschinen aus, entfernen sie manuell aus allen Pools, sie erhält keinen Verkehr mehr, führen Wartungsarbeiten durch, beheben etwas, und nachdem wir sie wieder in Betrieb nehmen, wird dieses Backup recht schnell aufgeholt. Das heißt, während der Ausfallzeit einer Maschine wird in ein paar Minuten aufgeholt. Das ist wirklich sehr wenig. Bei der Fehlertoleranz, wie gesagt, läuft hier alles super.

Was können wir aus diesem Backup-Schema zusammenfassen?

Wir haben Fehlertoleranz erhalten.

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

Wir haben einen doppelten Lesepuffer erhalten.

Das ist ein sehr guter Bonus zur Fehlertoleranz.

Aber es gibt auch Probleme. Jetzt haben wir eine viel komplexere Entwicklung von Funktionen, die damit zusammenhängen, da das System jetzt zu 100 % schließlich konsistent ist.

Architektur zur Speicherung und Auslieferung von Fotos in Badoo

Wir müssen zum Beispiel in einem Hintergrundjob ständig darüber nachdenken: 'Auf welchem Server sind wir gerade?', 'Gibt es hier wirklich das aktuelle Foto?' und so weiter. Das ist natürlich alles in Wrapper eingebunden, und für den Programmierer, der die Geschäftslogik schreibt, ist das transparent. Aber dennoch ist das ein großer, komplizierter Layer entstanden. Aber wir sind bereit, damit zu leben im Austausch für die Vorteile, die wir dadurch erhalten haben.

Und hier entsteht erneut ein gewisser Konflikt.

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

Ja, in der Tat hat sich die Situation im Laufe der Zeit stark verändert, und mittlerweile gibt es viele Vorteile in diesem Ansatz. Erstens haben wir eine viel einfachere Wartung.

Zweitens ist es leistungsfähiger, weil wir diese automatischen Controller für die Verbindung zu Festplattenspeichern nicht haben.

Dort gibt es eine riesige Maschinerie, aber hier sind einfach einige Festplatten, die hier auf der Maschine in einem RAID zusammengefasst sind.

Aber es gibt auch Nachteile.

Architektur zur Speicherung und Auslieferung von Fotos in Badoo

Das ist ungefähr 1,5-mal teurer als die Verwendung von SANs selbst zu heutigen Preisen. Daher haben wir beschlossen, nicht so mutig unseren gesamten großen Cluster in Maschinen mit lokalen Festplatten zu konvertieren und ein hybrides System zu übrig zu lassen.

Ein Teil der Maschinen arbeitet mit Festplatten (nun, nicht die Hälfte – wahrscheinlich etwa 30 Prozent). Der verbleibende Teil sind alte Maschinen, auf denen früher das erste Backup-Schema war. Wir haben sie einfach umgemountet, da wir keine neuen Daten oder ähnliches benötigen, wir haben nur die Mounts von einem physischen Host auf zwei übertragen.

Und wir haben einen großen Lesepuffer erhalten, und wir haben uns vergrößert. Wenn wir früher einen Speicher auf eine Maschine montiert haben, montieren wir jetzt zum Beispiel vier auf ein Paar. Und das funktioniert normal.

Lassen Sie uns eine kurze Zusammenfassung dessen geben, was wir erreicht haben, wofür wir gekämpft haben und ob es funktioniert hat.

Ergebnisse

Wir haben Nutzer – ganze 33 Millionen.

Wir haben drei Standorte – Prag, Miami, Hongkong.

In ihnen befindet sich eine Caching-Schicht, die aus Maschinen mit schnellen lokalen Festplatten (SSD) besteht, auf denen eine einfache Maschine mit NGINX, seinen access.log und Python-Daemons arbeitet, die alles verarbeiten und den Cache verwalten.

Falls gewünscht, können Sie in Ihrem Projekt, wenn Ihnen Fotos nicht so wichtig sind wie uns, oder wenn Ihr Trade-off zwischen Kontrolle und Geschwindigkeit zugunsten der Ressourcenkosten geht, ganz einfach auf ein CDN wechseln; moderne CDNs schaffen das gut.

Darauf folgt die Speicherschicht, in der wir Cluster aus Paaren von Maschinen haben, die sich gegenseitig sichern und asynchron Dateien von einer zu der anderen Kopie bei jeder Änderung.

Ein Teil dieser Maschinen arbeitet mit lokalen Festplatten.

Ein Teil dieser Maschinen ist an SANs angeschlossen.

Architektur zur Speicherung und Auslieferung von Fotos in Badoo

Einerseits ist das in der Handhabung bequemer und etwas leistungsfähiger, andererseits bietet es Vorteile hinsichtlich der Dichte und der Kosten pro Gigabyte.

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

Ein paar einfache Tipps von Cap.

Zunächst, falls Sie sich entscheiden, dass Sie dringend alles in Ihrer Foto-Infrastruktur verbessern müssen, messen Sie zuerst, denn möglicherweise gibt es nichts, was verbessert werden müsste.

Architektur zur Speicherung und Auslieferung von Fotos in Badoo

Ein Beispiel: Wir haben einen Cluster von Maschinen, der Fotos aus Anhängen in Chats ausliefert, und dort läuft immer noch das Schema von 2009, und niemand leidet darunter. Allen gefällt es.

Um zu messen, hängen Sie zunächst eine Menge Metriken an, schauen Sie sich diese an und entscheiden Sie dann, mit was Sie unzufrieden sind und was verbessert werden muss. Dafür haben wir ein tolles Werkzeug namens Pinba.

Es ermöglicht das Sammeln von sehr detaillierten Statistiken von NGINX für jede Anfrage sowie Antwortcodes und Zeitverteilungen — alles, was Sie wollen. Es hat Bindungen zu verschiedenen Analysesystemen, und Sie können alles schön betrachten.

Zuerst gemessen — dann verbessert.

Wir optimieren das Lesen mit Cache, das Schreiben mit Sharding, aber das ist offensichtlich.

Architektur zur Speicherung und Auslieferung von Fotos in Badoo

Wenn Sie gerade erst anfangen, Ihr System zu bauen, ist es viel besser, Fotos als immutable Dateien zu speichern. So verlieren Sie sofort eine ganze Klasse von Problemen mit Cache-Invalidierung und wie die Logik die richtige Version des Fotos finden sollte.

Architektur zur Speicherung und Auslieferung von Fotos in Badoo

Nehmen wir an, Sie haben ein Bild hochgeladen und anschließend gedreht, stellen Sie sicher, dass es sich um eine physisch andere Datei handelt. D.h. Sie müssen nicht denken: Ich spare ein wenig Platz, indem ich es in die gleiche Datei schreibe und die Version ändere. Das funktioniert immer schlecht und bringt später viel Kopfzerbrechen.

Der nächste Punkt: Resize zur Laufzeit.

Früher haben wir, als Benutzer ein Foto hochluden, sofort eine ganze Reihe von verschiedenen Größen für alle möglichen Anwendungsfälle geschnitten, die auf der Festplatte lagen. Jetzt haben wir das aufgegeben.

Wir haben nur drei Hauptgrößen beibehalten: klein, mittel und groß. Alles andere wird einfach aus der Größe, die hinter der angeforderten steht, heruntergerechnet — wir machen einfach Downsizing und geben es dem Benutzer.

Die CPU der Caching-Schicht ist hier viel günstiger, als wenn wir diese Größen auf jedem Speicher ständig neu generieren würden. Angenommen, wir möchten eine neue Größe hinzufügen, dann dauert das einen Monat — ein Skript, das das überall ordentlich macht, während der Cluster nicht überlastet wird. Das bedeutet, wenn Sie jetzt eine Entscheidung treffen können, ziehen Sie es vor, so wenige physische Größen wie möglich zu haben, aber mit einer gewissen Verteilung, sagen wir drei. Und alles andere einfach zur Laufzeit mit vorhandenen Modulen zu resize.

Und inkrementelles asynchrones Backup ist großartig.

Wie unsere Praxis gezeigt hat, funktioniert ein solches Schema hervorragend für das verzögerte Kopieren geänderter Dateien.

Architektur zur Speicherung und Auslieferung von Fotos in Badoo

Der letzte Punkt ist ebenso offensichtlich. Wenn Sie in Ihrer Infrastruktur jetzt keine solchen Probleme haben, aber es etwas gibt, das kaputtgehen könnte, wird es beständig kaputtgehen, wenn es ein wenig mehr wird. Daher ist es besser, im Voraus darüber nachzudenken und dabei keine Probleme zu haben. Das ist alles von meiner Seite.

Kontakte

» bo0rsh201
» Badoo Unternehmensblog

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

Wir sind bereits bereit, Konferenzprogramm, und der Zeitplan wird jetzt aktiv erstellt.

In diesem Jahr setzen wir unser Thema der Architektur und Skalierung fort:

Einige dieser Materialien verwenden wir auch in unserem Online-Kurs zur Entwicklung hochbelasteter Systeme HighLoad.Guide ist eine Reihe sorgfältig ausgewählter Briefe, Artikel, Materialien und Videos. In unserem Handbuch gibt es bereits über 30 einzigartige Materialien. Melden Sie sich an!

Quelle: habr.com

Erwerben Sie zuverlässiges Hosting für Websites mit DDoS-Schutz, VPS VDS-Server 🔥 Kaufen Sie zuverlässiges Hosting für Websites mit DDoS-Schutz, VPS VDS-Server | ProHoster