148 votes

Comment contourner le manque de transactions dans MongoDB?

Je sais qu'il ya des sujets similaires sur le site mais ils sont soit de me dire de revenir à la régulière systèmes SGBDR si j'ai besoin d'opérations ou d'utiliser des opérations atomiques ou de validation à deux phases. La deuxième solution semble le meilleur choix. La troisième est une façon, je ne veux pas les suivre, car il semble que beaucoup de choses pourraient aller mal et je ne peux pas le tester dans tous les aspects. Je vais avoir du mal à redéfinir mon projet pour répondre à la deuxième méthode. Je ne sais pas si cela provient du point de vue que j'ai parce que j'ai seulement travaillé avec des bases de données SQL la mesure ou il vraiment ne peut pas être fait.

Nous aimons tester MongoDB au sein de notre société. Nous avons choisi un relativement simple projet, qui est une passerelle SMS. Il permet à nos logiciels pour envoyer des messages SMS vers le réseau cellulaire et la passerelle ne le sale boulot: en fait, la communication avec les fournisseurs qui peuvent avoir différents protocoles de communication. La passerelle gère également la facturation des messages. Chaque client qui s'applique pour le service doivent acheter des crédits. Le système diminue automatiquement de l'équilibre de l'utilisateur lorsqu'un message est envoyé et refuse l'accès si le solde est insuffisant. Aussi parce que nous sommes des clients de tiers fournisseurs de SMS nous pouvons aussi nous avons notre propre équilibre. Nous devons garder la trace de ceux aussi bien.

J'ai commencé à penser comment puis-je stocker les données requises avec MongoDB si j'ai coupé une certaine complexité (facturation externe, en file d'attente d'envoi de SMS). Si je suis venu à partir de SQL monde je voudrais créer un tableau distinct pour les utilisateurs, une autre pour les messages SMS, et une pour stocker les transactions concernant les utilisateurs de l'équilibre. Disons que je créer des collections pour tous ceux dans MongoDB.

Imaginez un envoi de SMS tâche avec les étapes suivantes dans le système simplifié:

  1. vérifier si l'utilisateur dispose de suffisamment d'équilibre; refuser l'accès si il n'y a pas assez de crédit disponible

  2. d'envoyer et de stocker le message dans la collection de SMS avec les détails et le coût (dans le système live message aurait un statut d'attribut et d'une tâche de ramasser pour la livraison et le prix des SMS en fonction de son état actuel)

  3. réduire les utilisateurs de la balance avec le coût de l'envoyé de message

  4. journal de la transaction de la transaction collection

Maintenant, quel est le problème avec ça? MongoDB peut faire les mises à jour atomiques sur un seul document. Dans la précédente flux, il pourrait arriver qu'une erreur se glisse dans et le message est stocké dans la base de données, mais l'équilibre de l'utilisateur n'est pas réduite et/ou la transaction n'est pas connecté.

Je suis venu avec deux idées:

  • Créer une collection unique pour les utilisateurs, et de stocker le reste comme un champ, l'utilisateur opérations et les messages que sous les documents de l'utilisateur dans le document. Parce que nous pouvons mettre à jour les documents atomique, de la manière qu'il résout effectivement le problème de transaction. Inconvénients: si l'utilisateur envoie beaucoup de SMS, la taille du document pourrait devenir grand et le 4 MO document limite pourrait être atteint. Je peux peut-être créer de l'historique des documents dans de tels scénarios, mais je ne pense pas que ce serait une bonne idée. Aussi, je ne sais pas à quelle vitesse le système serait si je pousse de plus en plus de données pour le même document.

  • Créer une collection pour les utilisateurs, et un pour les transactions. Il peut y avoir deux types de transactions: achat à crédit avec un solde positif de changement et d'envoi de messages avec un solde négatif de changement. Transaction peut avoir un sous-document, par exemple par le message à envoyer les détails de SMS peut être inclus dans la transaction. Inconvénients: je n'ai pas de magasin de l'utilisateur actuel de la balance donc je dois le calculer à chaque fois qu'un utilisateur tente d'envoyer un message pour dire si le message pourrait aller ou pas. Je suis peur de ce calcul est devenu lent que le nombre de transactions stockées augmente.

Je suis un peu confus quel chemin choisir. Puis-je avoir d'autres solutions? Je n'ai pas trouver toutes les meilleures pratiques en ligne comment puis-je contourner ce genre de problèmes. Je suppose que beaucoup de programmeurs qui tentent de devenir familier dans le monde NoSQL face à des problèmes similaires dans les débuts.

26voto

Giovanni Bitliner Points 616

Regarde ça , par Tokutek. Ils développent un plugin pour Mongo qui promet non seulement des transactions, mais également une amélioration des performances.

12voto

Andreas Jung Points 1

En résumé: si l'intégrité transactionnelle est un impératif, n'utilisez pas MongoDB, mais utilisez uniquement des composants du système prenant en charge les transactions. Il est extrêmement difficile de créer quelque chose sur le composant afin de fournir une fonctionnalité similaire à ACID pour les composants non compatibles ACID. Selon les cas d'utilisation individuels, il peut être judicieux de séparer les actions en actions transactionnelles et non transactionnelles d'une manière ou d'une autre ...

8voto

pingw33n Points 6428

Maintenant, quel est le problème avec ça? MongoDB peut faire les mises à jour atomiques sur un seul document. Dans la précédente flux, il pourrait arriver qu'une erreur se glisse dans et le message est stocké dans la base de données, mais l'équilibre de l'utilisateur n'est pas est réduite et/ou la transaction est pas devient connecté.

Ce n'est pas vraiment un problème. L'erreur que vous avez mentionné est une logique (bug) ou IO error (réseau, panne de disque). Ce genre d'erreur peut laisser les deux transactionless et transactionnels dans les magasins de non-état cohérent. Par exemple, si elle a déjà envoyé des SMS, mais bien que le stockage de message d'erreur est survenue, il ne peut pas la restauration d'envoi de SMS, ce qui signifie qu'il ne sera pas connecté, l'utilisateur de la balance ne sera pas réduite etc.

Le vrai problème ici est que l'utilisateur peut profiter de la race, de condition et d'envoyer plus de messages que son équilibre permet. Ceci s'applique également aux SGBDR, à moins que vous ne l'envoi de SMS à l'intérieur de la transaction avec l'équilibre champ de verrouillage (ce qui serait un grand goulot d'étranglement). Une solution possible pour MongoDB serait l'aide d' findAndModify d'abord à la réduction de l'équilibre et de vérifier, si c'est négatif interdire l'envoi et de rembourser le montant atomiques (incrément). Si elle est positive, continuer à envoyer et en cas d'échec éventuel du montant du remboursement. Le solde de l'histoire de la collection peut être également maintenue pour aider à corriger/vérifier l'équilibre de terrain.

7voto

Karoly Horvath Points 45145

Le projet est simple, mais vous devez prendre en charge des transactions pour le paiement, ce qui rend la chose difficile. Ainsi, par exemple, un système de portail complexe avec des centaines de collections (forum, discussion en ligne, annonces, etc.) est à certains égards plus simple, car si vous perdez un forum ou une entrée de discussion, personne ne s'en soucie vraiment. Par contre, si vous perdez une opération de paiement, le problème est grave.

Donc, si vous voulez vraiment un projet pilote pour MongoDB, choisissez-en un qui est simple à cet égard.

7voto

kheya Points 2435

Les transactions sont absentes dans MongoDB pour des raisons valables. C'est l'une de ces choses qui font que MongoDB est plus rapide.

Dans votre cas, si la transaction est un must, le mongo ne semble pas être un bon choix.

Peut-être RDMBS + MongoDB, mais cela va ajouter des complexités et rendre plus difficile la gestion et le support des applications.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X