Options pour synchroniser efficacement 1 million de fichiers avec des serveurs distants?

27

Dans une entreprise pour laquelle je travaille, nous avons une telle chose appelée "listes de lecture" qui sont de petits fichiers ~ 100-300 octets chacun. Il y en a environ un million. Environ 100 000 d'entre eux sont changés toutes les heures. Ces listes de lecture doivent être téléchargées sur 10 autres serveurs distants sur différents continents toutes les heures et cela doit se produire rapidement en moins de 2 minutes, idéalement. Il est très important que les fichiers supprimés sur le maître soient également supprimés sur toutes les répliques. Nous utilisons actuellement Linux pour notre infrastructure.

Je pensais à essayer rsync avec l'option -W pour copier des fichiers entiers sans comparer le contenu. Je ne l'ai pas encore essayé mais peut-être que les gens qui ont plus d'expérience avec rsync pourraient me dire si c'est une option viable?

Quelles autres options méritent d'être envisagées?

Mise à jour: j'ai choisi l'option lsyncd comme réponse mais uniquement parce qu'elle était la plus populaire. D'autres alternatives suggérées sont également valables à leur manière.

Zilvinas
la source
1
Avez-vous un journal indiquant quels fichiers ont été modifiés ou supprimés?
Oliver
3
Si seulement les listes de lecture étaient des enregistrements mysql. Vous pouvez ensuite utiliser la réplication de base de données et obtenir mysql pour déterminer ce qui doit être envoyé / reçu.
Matt
@oliver que nous faisons. Cependant, vous devez faire confiance à ce journal, ce qui signifie que le code qui le génère doit être correct, puis vous avez besoin d'un code personnalisé pour traiter ce journal, qui doit également être correct. Je préfère éviter le code construit en interne pour le faire sur quelque chose qui a été largement testé par la communauté.
Zilvinas
Voulez - vous que le changement ne get appliqué toutes les heures? Ou la réplication instantanée est-elle également acceptable?
faker
1
Ne sous-estimez pas le temps nécessaire à rsync pour parcourir un million de fichiers. Essayez-le et vous verrez ce que vous faites. Si vous disposez de ce journal, utilisez-le ou essayez l'une des autres solutions proposées.
Oliver

Réponses:

39

Étant donné que les mises à jour instantanées sont également acceptables, vous pouvez utiliser lsyncd .
Il surveille les répertoires (inotify) et se rsynctransforme en esclaves.
Au démarrage, il fera un plein rsync, donc cela prendra un certain temps, mais après cela, seuls les changements sont transmis.
La surveillance récursive des répertoires est possible, si un serveur esclave est en panne, la synchronisation sera réessayée jusqu'à ce qu'elle revienne.

Si tout cela se trouve dans un seul répertoire (ou une liste statique de répertoires), vous pouvez également utiliser incron .
L'inconvénient est qu'il ne permet pas une surveillance récursive des dossiers et que vous devez implémenter vous-même la fonctionnalité de synchronisation.

truqueur
la source
Encore une astuce brillante :)
Zilvinas
1
+1 Il s'agit essentiellement d'un problème de cohérence du cache, un moniteur qui pousse les changements est la solution la plus simple. lsyncdimplémente que ...
Chris S
1
Je voudrais enquêter lsyncdet inotifyprofondément en ce qui concerne votre système d'exploitation serveur spécifique. Le nombre de montres inotify disponibles est limité. Je crois que la valeur par défaut est d'environ 1500 ou 8000 selon votre version Linux particulière. La plupart des noyaux vous permettent d'augmenter la limite, mais la surveillance d'un million de fichiers peut être plus importante que possible. Cela n'a pas fonctionné pour moi en 2008. De plus, la file d'attente des événements inotify peut déborder et vous faire perdre des événements, et vous devez avoir un moyen de récupérer de cela. Une mise en lsyncdœuvre soigneusement réglée et un quotidien rsyncpourraient fonctionner maintenant en 2012 pour couvrir vos bases.
Old Pro
2
En fait, il fait iontifysur le répertoire et non sur les fichiers individuels. Combien d'annuaires pouvez-vous regarder? Vérifiez /proc/sys/fs/inotify/max_user_watches(généralement 8192).
faker
2
Avec ~ 50k répertoires, inotify ne sera probablement pas bien mis à l'échelle. Lorsque nous avons essayé une approche similaire en 2009 avec 100 000 répertoires, il a fallu trop longtemps au noyau pour s'abonner à tous les répertoires. Quant à @OldPro, cela n'a pas fonctionné pour nous.
neovatar
11

Pensez à utiliser un système de fichiers distribué, tel que GlusterFS . Étant conçu avec la réplication et le parallélisme à l'esprit, GlusterFS peut évoluer jusqu'à 10 serveurs beaucoup plus facilement que les solutions ad hoc impliquant inotify et rsync.

Pour ce cas d'utilisation particulier, on pourrait créer un volume GlusterFS à 10 serveurs de 10 répliques (c'est-à-dire 1 réplique / brique par serveur), de sorte que chaque réplique soit un miroir exact de toutes les autres répliques du volume. GlusterFS propagerait automatiquement les mises à jour du système de fichiers vers toutes les répliques.

Les clients de chaque emplacement contacteraient leur serveur local, donc l'accès en lecture aux fichiers serait rapide. La question clé est de savoir si la latence d'écriture peut être maintenue à un niveau acceptable. La seule façon d'y répondre est de l'essayer.

Steven Monday
la source
+1 pour Glusterfs
Tom O'Connor
8

Je doute que rsynccela fonctionnerait normalement, car analyser un million de fichiers et le comparer 10 fois au système distant prendrait trop de temps. J'essaierais d'implémenter un système avec quelque chose comme inotifyça qui conserve une liste de fichiers modifiés et les pousse vers les serveurs distants (si ces modifications ne sont pas enregistrées d'une autre manière de toute façon). Vous pouvez ensuite utiliser cette liste pour identifier rapidement les fichiers à transférer - peut-être même avec rsync (ou mieux 10 instances parallèles).

Edit: Avec un peu de travail, vous pouvez même utiliser cette approche inotify / log watch pour copier les fichiers dès que la modification se produit.

Sven
la source
5

Quelques alternatives:

  • Insérez un travail dans RabbitMQ ou Gearman pour éteindre de manière asynchrone et supprimer (ou ajouter) le même fichier sur tous les serveurs distants chaque fois que vous supprimez ou ajoutez un fichier sur le serveur principal.
  • Stockez les fichiers dans une base de données et utilisez la réplication pour garder les serveurs distants synchronisés.
  • Si vous avez ZFS, vous pouvez utiliser la réplication ZFS .
  • Certains SAN ont une réplication de fichiers. Je ne sais pas si cela peut être utilisé sur Internet.
Ladadadada
la source
4

Cela semble être un cas d'utilisation idéal pour MongoDB et peut-être GridFS . Étant donné que les fichiers sont relativement petits, MongoDB seul devrait suffire, bien qu'il puisse être pratique d'utiliser l'API GridFS.

MongoDB est une base de données nosql et GridFS est un stockage de fichiers construit par-dessus. MongoDB a beaucoup d'options intégrées pour la réplication et le partitionnement , donc il devrait très bien évoluer dans votre cas d'utilisation.

Dans votre cas, vous commencerez probablement avec un jeu de répliques composé du maître situé dans votre centre de données principal (peut-être un deuxième, au cas où vous voudriez basculer au même endroit) et vos dix "esclaves" répartis dans le monde. Effectuez ensuite des tests de charge pour vérifier si les performances d'écriture sont suffisantes et vérifiez les temps de réplication sur vos nœuds. Si vous avez besoin de plus de performances, vous pouvez transformer la configuration en une partition (principalement pour répartir la charge d'écriture sur plus de serveurs). MongoDB a été conçu pour mettre à l'échelle d'énormes configurations avec du matériel «bon marché», de sorte que vous pouvez ajouter un lot de serveurs bon marché pour améliorer les performances.

néovatar
la source
0

J'utiliserais un backend S3, puis je le monterais sur tous les serveurs dont j'ai besoin - De cette façon, tout le monde est synchronisé instantanément de toute façon

Mister IT Guru
la source
Bien que le stockage soit synchronisé, vous devez en informer l'application, vous devez donc revenir à la case départ, ou l'application doit interroger le stockage chaque fois que quelqu'un accède à ces listes de lecture. Les performances seraient horribles dans les deux cas.
Chris S
L'application n'a pas besoin d'interroger le stockage chaque fois que quelqu'un accède aux listes de lecture, juste assez de fois dans l'heure pour s'assurer que l'application fonctionne sans données périmées. De plus, si S3 est utilisé comme backend, pourquoi l'application devrait-elle interroger les fichiers en premier lieu? Ils seront toujours à jour
Mister IT Guru
0

Une option qui ne semble pas avoir encore été mentionnée consiste à archiver tous les fichiers dans un fichier compressé. Cela devrait réduire considérablement la taille totale et supprimer tous les frais généraux que vous obtenez en traitant des millions de fichiers individuels. En remplaçant l'ensemble de fichiers en une seule mise à jour, vous pouvez également être assuré que les fichiers supprimés sont supprimés sur les répliques.

L'inconvénient est bien sûr que vous transférez inutilement de nombreux fichiers. Cela peut ou non être compensé par la taille réduite grâce à la compression. De plus, je n'ai aucune idée du temps qu'il faudrait pour compresser autant de fichiers.

Supr
la source