Optionen zum effizienten Synchronisieren von 1 Million Dateien mit Remote-Servern?


27

In einer Firma, für die ich arbeite, gibt es so etwas wie "Wiedergabelisten", bei denen es sich um kleine Dateien mit jeweils 100 bis 300 Bytes handelt. Es gibt ungefähr eine Million von ihnen. Ungefähr 100.000 von ihnen werden jede Stunde gewechselt. Diese Wiedergabelisten müssen stündlich auf 10 andere Remote-Server auf verschiedenen Kontinenten hochgeladen werden, und im Idealfall dauert es weniger als 2 Minuten. Es ist sehr wichtig, dass Dateien, die auf dem Master gelöscht werden, auch auf allen Replikaten gelöscht werden. Derzeit verwenden wir Linux für unsere Infrastruktur.

Ich dachte darüber nach, rsync mit der Option -W zu versuchen, um ganze Dateien zu kopieren, ohne den Inhalt zu vergleichen. Ich habe es noch nicht ausprobiert, aber vielleicht können mir Leute, die mehr Erfahrung mit rsync haben, sagen, ob es eine praktikable Option ist?

Welche anderen Optionen sind eine Überlegung wert?

Update: Ich habe die Option lsyncd als Antwort gewählt, aber nur, weil sie am beliebtesten war. Andere vorgeschlagene Alternativen haben ebenfalls ihre eigene Gültigkeit.


1
Haben Sie ein Protokoll, das angibt, welche Dateien geändert oder gelöscht wurden?
Oliver

3
Wenn nur die Wiedergabelisten MySQL-Datensätze wären. Sie könnten dann die Datenbankreplikation verwenden und mit mysql herausfinden, was gesendet / empfangen werden muss.
Matt

@oliver wir tun. Dann müssen Sie jedoch diesem Protokoll vertrauen, was bedeutet, dass der erzeugende Code korrekt sein muss, und dann benötigen Sie benutzerdefinierten Code, um das Protokoll zu verarbeiten, das auch korrekt sein muss. Ich vermeide lieber selbst erstellten Code, um dies über etwas zu tun, das von der Community ausgiebig getestet wurde.
Zilvinas

Möchten Sie, dass die Änderung nur stündlich angewendet wird? Oder ist die Sofortreplikation auch akzeptabel?
Fälscher

1
Unterschätzen Sie nicht die Zeit, die rsync benötigt, um eine Million Dateien zu verarbeiten. Probieren Sie es einfach aus und Sie werden sehen, was Sie vorhaben. Wenn Sie dieses Protokoll haben, verwenden Sie es oder probieren Sie eine andere der vorgeschlagenen Lösungen aus.
Oliver

Antworten:


39

Da auch sofortige Aktualisierungen zulässig sind, können Sie lsyncd verwenden .
Es überwacht Verzeichnisse (inotify) und rsyncverwandelt sich in Slaves.
Beim Start wird ein vollständiger rsyncVorgang ausgeführt, der einige Zeit in Anspruch nimmt. Danach werden jedoch nur die Änderungen übertragen.
Das rekursive Überwachen von Verzeichnissen ist möglich. Wenn ein Slave-Server ausfällt, wird die Synchronisierung wiederholt, bis sie wieder hergestellt wird.

Wenn sich dies alles in einem einzelnen Verzeichnis (oder einer statischen Liste von Verzeichnissen) befindet, können Sie auch incron verwenden .
Der Nachteil dabei ist, dass das rekursive Überwachen von Ordnern nicht möglich ist und Sie die Synchronisierungsfunktion selbst implementieren müssen.


Wieder ein
großartiger

1
+1 Dies ist im Wesentlichen ein Cache-Kohärenzproblem. Ein Monitor, der Änderungen überträgt, ist die einfachste Lösung. lsyncdimplementiert, dass ...
Chris S

1
Ich würde nachforschen lsyncdund inotifyzutiefst auf Ihr spezifisches Server-Betriebssystem zutreffen. Die Anzahl der verfügbaren inotify-Uhren ist begrenzt. Ich glaube, die Standardeinstellung liegt bei 1500 oder 8000, abhängig von Ihrer speziellen Linux-Version. Bei den meisten Kerneln können Sie das Limit erhöhen, aber die Überwachung von 1 Million Dateien kann mehr sein, als praktisch ist. 2008 hat es bei mir nicht funktioniert. Außerdem kann die Warteschlange für inotifizierte Ereignisse überlaufen, sodass Sie Ereignisse verlieren. Sie müssen einen Weg finden, sich davon zu erholen. Eine sorgfältig abgestimmte lsyncdImplementierung und eine tägliche Implementierung rsynckönnten jetzt 2012 funktionieren, um Ihre Grundlagen abzudecken.
Old Pro

2
Eigentlich macht man iontifyauf dem Verzeichnis nicht die einzelnen Dateien. Wie viele Verzeichnisse können Sie sehen? Überprüfen Sie /proc/sys/fs/inotify/max_user_watches(normalerweise 8192).
Fälscher

2
Mit ~ 50k Verzeichnissen wird inotify möglicherweise nicht gut skaliert. Als wir 2009 einen ähnlichen Ansatz mit 100.000 Verzeichnissen versuchten, dauerte es lange, bis der Kernel alle Verzeichnisse abonniert hatte. Bei @OldPro hat es bei uns nicht funktioniert.
Neovatar

11

Erwägen Sie die Verwendung eines verteilten Dateisystems wie GlusterFS . GlusterFS wurde unter Berücksichtigung von Replikation und Parallelität entwickelt und kann bis zu 10 Server problemloser skalieren als Ad-hoc-Lösungen mit inotify und rsync.

Für diesen speziellen Anwendungsfall kann ein GlusterFS-Volume mit 10 Servern mit 10 Replikaten (dh 1 Replikat / Brick pro Server) erstellt werden, sodass jedes Replikat ein exakter Spiegel jedes anderen Replikats im Volume ist. GlusterFS würde Dateisystemaktualisierungen automatisch auf alle Replikate übertragen.

Clients an jedem Standort würden sich an ihren lokalen Server wenden, sodass der Lesezugriff auf Dateien schnell erfolgen würde. Die entscheidende Frage ist, ob die Schreiblatenz akzeptabel niedrig gehalten werden kann. Die einzige Möglichkeit, dies zu beantworten, besteht darin, es zu versuchen.


+1 für Glusterfs
Tom O'Connor

8

Ich bezweifle rsync, dass dies auf normale Weise funktionieren würde, da das zehnmalige Scannen einer Million Dateien und das Vergleichen mit dem Remote-System zu lange dauern würde. Ich würde versuchen, ein System mit so etwas zu implementieren inotify, das eine Liste der geänderten Dateien enthält und diese auf die Remote-Server überträgt (falls diese Änderungen nicht auf andere Weise protokolliert werden). Mithilfe dieser Liste können Sie dann schnell die zu übertragenden Dateien identifizieren - möglicherweise sogar mit rsync (oder besser 10 parallelen Instanzen davon).

Bearbeiten: Mit ein wenig Arbeit können Sie sogar diesen Inotify / Log-Watch-Ansatz verwenden, um die Dateien zu kopieren, sobald die Änderung erfolgt.


5

Einige weitere Alternativen:

  • Fügen Sie einen Auftrag in RabbitMQ oder Gearman ein , um dieselbe Datei auf allen Remote-Servern asynchron zu löschen (oder hinzuzufügen), wenn Sie eine Datei auf dem Primärserver löschen oder hinzufügen.
  • Speichern Sie die Dateien in einer Datenbank und verwenden Sie die Replikation, um die Remote-Server synchron zu halten.
  • Wenn Sie über ZFS verfügen , können Sie die ZFS-Replikation verwenden .
  • Einige SANs verfügen über eine Dateireplikation. Ich habe keine Ahnung, ob dies über das Internet genutzt werden kann.

4

Dies scheint ein idealer Storybook-Anwendungsfall für MongoDB und möglicherweise GridFS zu sein . Da die Dateien relativ klein sind, sollte MongoDB alleine ausreichen, obwohl es möglicherweise praktisch ist, die GridFS-API zu verwenden.

MongoDB ist eine NOSQL-Datenbank und GridFS ist ein Dateispeicher, der darauf aufbaut. MongoDB verfügt über eine Vielzahl integrierter Optionen für Replikation und Sharding. Daher sollte es in Ihrem Anwendungsfall sehr gut skalierbar sein .

In Ihrem Fall werden Sie wahrscheinlich mit einem Replikatsatz beginnen, der aus dem Master in Ihrem primären Datencenter (möglicherweise einem zweiten, falls Sie ein Failover am selben Ort durchführen möchten) und Ihren zehn weltweit verteilten "Slaves" besteht. Führen Sie dann Ladetests durch, um zu überprüfen, ob die Schreibleistung ausreicht, und überprüfen Sie die Replikationszeiten auf Ihren Knoten. Wenn Sie mehr Leistung benötigen, können Sie das Setup in ein Sharded-Setup umwandeln (hauptsächlich, um die Schreiblast auf mehrere Server zu verteilen). MongoDB wurde mit dem Ziel entwickelt, riesige Setups mit "billiger" Hardware zu skalieren, sodass Sie eine Reihe kostengünstiger Server einsetzen können, um die Leistung zu verbessern.


0

Ich würde ein S3-Backend verwenden und dieses dann einfach auf allen Servern einbinden, die ich benötige. Auf diese Weise sind sowieso alle sofort synchron


Während der Speicher synchronisiert würde, müssten Sie die Anwendung benachrichtigen, damit Sie wieder auf Platz eins kommen, oder die App müsste den Speicher jedes Mal abrufen, wenn jemand auf diese Wiedergabelisten zugreift. Leistung wäre in jedem Fall schrecklich.
Chris S

Die Anwendung muss den Speicher nicht jedes Mal abrufen, wenn jemand auf die Wiedergabelisten zugreift. Dies ist jedoch ausreichend, um sicherzustellen, dass die Anwendung ohne veraltete Daten ausgeführt wird. Wenn S3 als Backend verwendet wird, warum muss die Anwendung die Dateien überhaupt abrufen? Sie werden immer auf dem neuesten Stand sein
Mister IT Guru

0

Eine Option, die anscheinend noch nicht erwähnt wurde, besteht darin, alle Dateien in einer komprimierten Datei zu archivieren. Dies sollte die Gesamtgröße erheblich reduzieren und den gesamten Overhead aus dem Umgang mit Millionen einzelner Dateien entfernen. Durch Ersetzen der gesamten Dateigruppe in einem großen Update können Sie auch sicher sein, dass entfernte Dateien auf den Replikaten entfernt werden.

Der Nachteil ist natürlich, dass Sie viele Dateien unnötig übertragen. Dies kann durch die verringerte Größe dank Komprimierung ausgeglichen werden oder nicht. Ich habe auch keine Ahnung, wie lange es dauern würde, so viele Dateien zu komprimieren.

Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.