2013-04-13 5 views
4

ma collection MongoDB est utilisée comme file d'attente, et 3 machines C++ lisent à partir de cette collection. Le problème est que ces trois ne peuvent pas effectuer le même travail. Tous les travaux doivent être effectués une seule fois.MongoDB findAndModify à partir de plusieurs clients

Je récupère tous les travaux non terminés en recherchant dans la collection tous les enregistrements avec 'isDone: False', puis je mets à jour ce document 'isDone: True'. Mais si deux machines trouvent le même document en même temps, elles le feront toutes les deux. Comment puis-je éviter ça?

Modifier: Ma question est - est-ce que findAndModify résout vraiment ce problème? (Après avoir lu A way to ensure exclusive reads in MongoDb's findAndModify?)

+0

Je suis confus au sujet de votre question.Le point entier de 'findAnyModify' est qu'il trouve et modifie atomiquement un document en une seule opération, évitant ainsi ce problème. – JohnnyHK

+0

Je me demande si c'est vraiment après avoir vu http://stackoverflow.com/questions/15505176/a-way-to-ensure-exclusive-reads-in-mongodbs-findandmodify –

+0

@EiTkoCaT http://stackoverflow.com/a/15539348/829571 – assylias

Répondre

1

Oui, findAndModify le résout.

Ref: MongoDB findAndModify from multiple clients » ... Note: Cette commande permet d'obtenir un verrou d'écriture sur la base de données affectée et bloquerons d'autres opérations jusqu'à ce qu'il ait terminé, mais généralement le verrou d'écriture est de courte durée et équivalente à d'autres mise à jour similaire() opérations ... «

Ref: http://docs.mongodb.org/manual/reference/method/db.collection.update/#db.collection.update ». ... Pour les collections unsharded, vous pouvez modifier ce comportement avec l'opérateur d'isolement isolé $, qui isole l'opération de mise à jour et bloque d'autres opérations d'écriture au cours de la mise à jour Voir l'opérateur d'isolement ... "

Ref: http://docs.mongodb.org/manual/reference/operator/isolated/

Cordialement, Moacy

0

Oui, retrouvez-et-modification résoudra votre problème:

db.collection.findAndModify ({ requête: {isDone: false}, mise à jour: {$ set: {isDone: true}}, new: true, upsert: false # ne crée jamais de nouveaux documents });

Cela retournera un document unique qu'il vient de mettre à jour de faux à vrai.

Mais vous avez un sérieux problème si vos clients C++ ont un hiccup (la boîte meurt, ils sont tués, le code a une erreur, etc.) Imaginez si votre connexion TCP tombe juste après la mise à jour sur le serveur, mais avant que le code C++ obtienne le travail. Il est généralement préférable d'avoir l'approche en plusieurs phases:

  • changement « isDone » à « isInProgress », puis quand il est fait, supprimer le document. (Maintenant, vous pouvez voir la pile de "todo" et "être fait" .Si quelque chose est "en cours" pendant une longue période, le client est probablement mort

  • changer "isDone" en "phase" et atomiquement le mettre de « nouvelle » à « commencé » (et plus tard, il est réglé sur « terminé »). maintenant, vous pouvez voir si quelque chose est « a commencé » depuis longtemps, le client peut-être mort.

Si vous êtes vraiment sophistiqué, vous pouvez faire un index partiel.Par exemple, "Seulement indexer avec" phase: {$ ne: 'terminé'} ".Vous n'avez plus besoin de gaspiller de l'espace en indexant les millions de documents finis. L'index ne contient que la poignée de documents nouveaux/en cours, c'est donc plus petit/plus rapide

Questions connexes