2011-06-08 4 views
10

Je suis en train de construire un système où S3 sera utilisé comme un hash-set persistant (l'URL S3 est déduite des données) par beaucoup d'ordinateurs sur Internet. Si deux nœuds stockent les mêmes données, ils seront stockés avec la même clé et ne seront donc pas stockés deux fois. Lorsqu'un objet est supprimé, j'ai besoin de savoir si d'autres nœuds utilisent également ces données. Dans ce cas, je ne vais pas l'enlever. En ce moment, je l'ai implémenté en ajoutant une liste des nœuds de stockage dans les données écrites en S3. Ainsi, lorsqu'un nœud stocke les données, les événements suivants se produisent:Concurrence dans Amazon S3

  1. Lire l'objet de S3.
  2. Désérialise l'objet. Ajoutez l'ID du nouveau nœud à la liste des nœuds de stockage.
  3. Sérialiser le nouvel objet (les données à stocker et la liste de nœuds).
  4. Ecrivez les données sérialisées dans S3.

Ceci crée une forme de comptage de références idempotentes. Puisque les demandes sur Internet peuvent être assez peu fiables, je ne veux pas simplement compter le nombre de nœuds de stockage. C'est pourquoi je stocke une liste à la place d'un compteur (dans le cas où un nœud envoie la même requête> 1 fois).

Cette approche fonctionne tant que deux nœuds n'écrivent pas simultanément. S3 (pour autant que je sache) ne fournit aucun moyen de verrouiller l'objet de sorte que toutes ces 5 étapes deviennent atomiques.

Comment voulez-vous résoudre ce problème de simultanéité? Je considère l'implémentation d'une certaine forme de concurrence optimiste. Comment dois-je faire pour S3? Devrais-je utiliser une approche complètement différente?

Répondre

4

Envisagez d'abord de séparer la liste de verrouillage de vos données (protégées). Créez un compartiment distinct spécifique à vos données pour contenir la liste de verrouillage (le nom du compartiment doit être une dérivée de votre nom d'objet de données). Utilisez des fichiers individuels dans ce second compartiment (un par nœud, avec le nom de l'objet dérivé du nom du nœud). Les noeuds ajoutent un nouvel objet au second compartiment avant d'accéder aux données protégées, les noeuds retirent leur objet du second compartiment lorsqu'ils sont terminés.

Ceci vous permet d'énumérer le second compartiment pour déterminer si vos données sont verrouillées. Et permet à deux nœuds de mettre à jour la liste de verrous simultanément sans conflit.

+0

J'aime l'idée! Cela fonctionne pour les écritures, puisque S3 a maintenant une consistance read-after-write mais je suppose que nous risquons toujours de ne pas supprimer un objet, car il n'a pas de cohérence read-after-delete. – Yrlec

1

Il peut être judicieux de séparer les références de la ressource.

Vous pouvez créer une simultanéité en plus de la gestion des versions S3. Ou laisser chaque référent/nœud créer et supprimer sa propre ressource de verrouillage sur S3. Ou utilisez le service RDS (Amazon Relational Database Service).

+0

Merci, mais nous le faisons à une telle échelle que nous préférons éviter d'utiliser RDS (qui a une évolutivité limitée) et SimpleDB (qui a des coûts d'E/S élevés). – Yrlec

3

Pour ajouter à ce qu'Amadeus dit, si vos besoins ne sont pas relationnels, vous pouvez même utiliser SimpleDB d'AWS, nettement moins cher.

+0

Merci, mais la taille de nos objets (un couple de Mo/objet) fait de SimpleDB une option très chère (peut-être même impossible). – Yrlec

2

Je n'ai pas travaillé avec Amazon S3, mais voici ma suggestion ignorant la persistance.

  1. Pouvez-vous utiliser la ségrégation de requête de commande? Sera agréable de séparer les lectures des commandes, car cette vérification ne se produira que pour la commande (DELETE) et vous n'en aurez pas besoin pour les lectures (si je l'ai eu correctement). S'il n'y a pas de support natif pour une telle synchronisation, alors votre solution enroulée peut être un goulot d'étranglement en termes de charge élevée (ce qui peut être résolu par [3] et [4]). Tous vos DELETE doivent passer par une place centrale - file d'attente de requêtes.

  2. Je ferais un service dédié (comme WCF) avec une file d'attente de requêtes simultanées. Chaque fois que vous devez SUPPRIMER un objet, vous mettez en file d'attente un élément. Le service, à son propre rythme, supprimera l'article et fera toutes les 5 étapes en une seule transaction. Cela peut entraîner des retards, qui peuvent toutefois ne pas être visibles si le système est trop lourd.

  3. Si le système est en écriture lourd, vous devrez peut-être ajouter les travailleurs qui aident à dequeue la demande de la file d'attente [3]

+0

Merci! Oui, utiliser une sorte de file d'attente est une façon de le résoudre (par exemple en utilisant SQS). Cependant, je le ferais aussi pour les écritures, pas seulement pour les suppressions (sinon certains nœuds ajoutés pourraient être perdus). Mon souci avec ceci est que cela pourrait devenir soit trop cher (SQS devenir un coût supplémentaire) ou que le débit n'est pas assez bon. Faire une concurrence optimiste pourrait résoudre cela. Cependant, je n'ai jamais implémenté quelque chose comme ça auparavant, donc je m'inquiète un peu d'introduire un bogue bizarre (puisqu'il est difficile de tester les problèmes de concurrence). – Yrlec

+0

@Yrlec, je ne savais pas Amazon a * SQS *. Je pensais plutôt à un service * WCF * autonome sur * MSMQ *, ou * Mass Transit * ou * NServiceBus *. La bonne chose au sujet de faire la queue - vous pouvez avoir un seul thread pour faire la queue et les travailleurs à plusieurs dequeue il (chaque demande est une opération atomique distincte qui ne partage pas les données, si cela est possible). Peut-être que vous pouvez également essayer des techniques sans verrou pour effectuer les opérations qui ont besoin de synchronisation - ce qui est encore plus problématique. – oleksii

0

Vous pouvez implémenter votre propre mécanisme de verrouillage en tant que service sur votre EC2 et l'utiliser pour synchroniser les accès à S3. Dans ce cas, vous pouvez stocker des décomptes de surveillance dans votre S3 (séparément ou non)

+0

Dans ce cas, vous devez vous conformer aux performances des services Amazon dans votre implémentation, ou cela sera probablement un goulot d'étranglement dans votre chaîne –