web-dev-qa-db-fra.com

Que se passe-t-il s'il y a trop d'inserts dans MongoDB? Comment s'assurer que toutes les données sont stockées?

J'utilise MongoDB pour stocker des valeurs mesurées périodiquement. Toutes les ~ 100 ms, un groupe de valeurs est inséré en tant que document. Cela fonctionne bien, mais je m'inquiète des problèmes de performances. (J'utilise des insertions sûres, il semble que dans PyMongo c'est la valeur par défaut.)

Que se passe-t-il s'il y a plus d'insertions par seconde que mongod ne peut enregistrer sur le disque dur? Y aura-t-il un avertissement ou échouera-t-il simplement en silence?

Existe-t-il une méthode pour surveiller la charge d'écriture? Je n'ai trouvé que db.serverStatus().writeBacksQueued qui est toujours définie sur false lorsque je l'appelle. Comment puis-je tester la quantité de données que je dois insérer pour remplir la file d'attente d'écriture?

mongostat affiche les verrous. Est-ce quelque chose qui devrait m'inquiéter?

insert  query update delete getmore command flushes mapped  vsize    res faults  locked db idx miss %     qr|qw   ar|aw  netIn netOut  conn repl       time 
  *117     *0     *0     *0       0     2|0       0  17.4g  35.3g  3.76g      0     .:6.5%          0       0|0     0|0   124b     6k     2  SLV   09:58:10 
  *111     *0     *0     *0       0     2|0       0  17.4g  35.3g  3.76g      0     .:0.8%          0       0|0     0|0   124b     6k     2  SLV   09:58:11 
  *111     *0     *0     *0       0     2|0       0  17.4g  35.3g  3.76g      0     .:4.2%          0       0|0     0|0   124b     6k     2  SLV   09:58:1

Dois-je m'inquiéter des verrous d'écriture? Qu'arrive-t-il à un insert pendant une période verrouillée en écriture? Est-il mis en file d'attente et stocké plus tard?

Je pense à une configuration de réplication simple utilisant un maître et un esclave. La synchronisation initiale ou un processus de resynchronisation verrouille-t-il les bases de données?

(J'utilise la version 2.4.3.)

Mise à jour: Je pense avoir répondu en partie à ma propre question. J'ai réussi à obtenir jusqu'à 12 000 insertions par seconde en utilisant une simple boucle while en insérant un petit document de test. Mais qr | qw montre toujours que la file d'attente de lecture et d'écriture est toujours vide:

insert  query update delete getmore command flushes mapped  vsize    res faults       locked db idx miss %     qr|qw   ar|aw  netIn netOut  conn repl       time 
 11234     *0      2     *0    1563     1|0       1  21.9g  44.3g  1.22g      0    testdb:58.9%          0       1|0     1|1   797k   980k     6  PRI   10:26:32 
 12768     *0      2     *0    1284     1|0       0  21.9g  44.3g  1.22g      0    testdb:58.0%          0       0|0     0|1   881k     1m     6  PRI   10:26:33 
 12839     *0      2     *0    1231     1|0       0  21.9g  44.3g  1.22g      0    testdb:60.3%          0       0|0     0|1   883k     1m     6  PRI   10:26:34 
 12701     *0      2     *0     910     1|0       0  21.9g  44.3g  1.22g      0    testdb:61.8%          0       0|0     0|1   858k     1m     6  PRI   10:26:35 
 12241     *0      2     *0    1206     1|0       0  21.9g  44.3g  1.22g      0    testdb:56.7%          0       0|0     0|0   843k     1m     6  PRI   10:26:36 
 11581     *0      2     *0    1406     1|0       0  21.9g  44.3g  1.22g      0    testdb:61.8%          0       0|0     0|1   811k     1m     6  PRI   10:26:37 
  8719     *0      2     *0    1210     1|0       0  21.9g  44.3g  1.22g      0    testdb:43.8%          0       0|0     0|1   618k   762k     6  PRI   10:26:38 
 11429     *0      2     *0    1469     1|0       0  21.9g  44.3g  1.22g      0    testdb:60.6%          0       0|0     0|1   804k   993k     6  PRI   10:26:39 
 12779     *0      2     *0    1092     1|0       0  21.9g  44.3g  1.22g      0    testdb:60.2%          0       1|0     0|1   872k     1m     6  PRI   10:26:40 
 12757     *0      2     *0     436     1|0       0  21.9g  44.3g  1.22g      0    testdb:59.7%          0       0|0     0|1   838k   432k     6  PRI   10:26:41 

Je suppose que cela signifie que les insertions seules ne causeront pas beaucoup de problèmes: "Les files d'attente auront tendance à augmenter si vous effectuez beaucoup d'opérations d'écriture aux côtés d'autres opérations d'écriture lourdes, telles que les suppressions à grande échelle." (trouvé ici ]

Ma question ouverte: Qu'advient-il de mes données si la file d'attente d'écriture augmente à long terme?

24
lumbric

Vous avez répondu à certaines de vos propres questions ici, en particulier vous avez une idée décente de l'aspect de verrouillage d'écriture de l'équation - 12 000 insertions/sec vous amène à ~ 60% de verrouillage d'écriture. C'est un niveau raisonnable pour obtenir des performances cohérentes - vous obtiendrez des conflits et certaines opérations seront un peu plus lentes, mais vous voulez vraiment commencer à vous inquiéter à environ 80% - comme beaucoup de choses, lorsque vous commencez à dépasser 80% disponibles capacité, vous commencerez à frapper les problèmes beaucoup plus souvent.

En termes d'autres goulots d'étranglement, et en particulier de la vitesse à laquelle vous pouvez écrire sur le disque - cela peut causer des problèmes, mais pour regarder les statistiques pertinentes au fil du temps, je recommanderais d'obtenir MMS installé avec le plugin munin-node pour vous fournir du matériel et des statistiques IO en plus des statistiques MongoDB.

Lorsque vous avez cela, les mesures que vous voudrez surveiller sont:

  • Le temps de vidage moyen (c'est la durée de la synchronisation périodique de MongoDB sur le disque)
  • Les IOStats dans l'onglet matériel (IOWait en particulier)
  • Défauts de page (si votre disque est occupé par des écritures et que vous avez besoin de lire des données, ils vont être en concurrence pour une ressource rare)

C'est un peu compliqué alors, mais voici une idée de base:

  • Lorsque le temps de rinçage moyen commence à augmenter, soyez inquiet
  • S'il atteint plusieurs secondes, vous êtes probablement à la limite (bien que cela dépende du volume de données écrites et de la vitesse du disque)
  • Si elle approche 60 secondes, vous verrez les performances se dégrader gravement (le vidage se produit toutes les 60 secondes, donc elles seraient essentiellement en file d'attente)
  • Un IOWait élevé va également nuire aux performances, surtout si vous devez lire à partir du disque à tout moment
  • Par conséquent, la recherche des niveaux de défaut de page sera également importante

L'autre morceau de ce puzzle, que nous n'avons pas encore mentionné, est le journal. Ces données seront également conservées sur le disque (par défaut toutes les 100 ms) et elles s'ajouteront donc à la charge du disque si elle se trouve sur le même volume. Par conséquent, si vous constatez une utilisation élevée du disque, déplacer le journal vers un autre disque serait une bonne idée.

Il n'y a pas de véritables "nombres magiques" pour rester en dessous, dans la plupart des cas, tout est relatif, alors obtenez une bonne base de référence pour votre trafic normal, vérifiez si les choses évoluent et peut-être testez la charge pour voir quelles sont vos limites et quand les choses commencer à se dégrader et vous serez en bonne forme.

Après tout ce préambule, passons à certaines de vos questions:

Que se passe-t-il s'il y a plus d'insertions par seconde que mongod ne peut enregistrer sur le disque dur? Y aura-t-il un avertissement ou échouera-t-il simplement en silence?

Si vous commencez à stresser le disque aux niveaux décrits ci-dessus, tout finira par ralentir et à un moment donné (et cela dépendra des délais, de la force de votre matériel, de la façon dont vous gérez les exceptions) vos écritures échoueront - si vous utilisez une version récente de pymongo, vous utiliserez par défaut des écritures sûres et celles-ci échoueront. Si vous souhaitez être un peu plus paranoïaque, vous pouvez parfois faire un souci d'écriture de j: true qui attendra pour retourner OK jusqu'à ce que l'écriture soit parvenue au journal (c'est-à-dire sur le disque). Bien sûr, cela sera plus lent qu'une écriture sûre normale, mais ce sera une indication immédiate des problèmes liés à la capacité du disque, et vous pouvez l'utiliser pour bloquer/mettre en file d'attente d'autres opérations et agir essentiellement comme un accélérateur pour empêcher votre base de données d'être submergé.

Je pense à une configuration de réplication simple utilisant un maître et un esclave. La synchronisation initiale ou un processus de resynchronisation verrouille-t-il les bases de données?

Je pense que j'ai couvert le verrouillage global au début, mais pour répondre spécifiquement à cette pièce: Tout d'abord, assurez-vous que vous utilisez un jeu de répliques , pas maître/esclave. L'implémentation maître/esclave est obsolète et n'est pas recommandée pour une utilisation en général. Quant à la synchronisation initiale, elle ajoutera une certaine charge au primaire en termes de lectures, mais pas en termes d'écritures, vous devriez donc être bien en termes de verrouillage.

Qu'advient-il de mes données si la file d'attente d'écriture augmente à long terme?

Comme vous pouvez probablement le voir à partir de l'explication ci-dessus, la réponse dépend beaucoup de la façon dont vous écrivez votre demande, de la façon dont vous choisissez de faire reconnaître vos écritures et de la capacité dont vous disposez. Vous pouvez, pour l'essentiel, être aussi sûr que vous le souhaitez quand il s'agit d'écrire sur le disque sur MongoDB, mais il y a un compromis entre les performances, comme mentionné avec la discussion j:true Ci-dessus.

Généralement, vous voulez déterminer votre facteur limitant - que ce soit le verrouillage, la vitesse du disque, etc., puis suivre les niveaux au fil du temps et évoluer (sharding) ou augmenter (meilleur matériel) avant d'atteindre une limite stricte et de voir des problèmes de performances.

Une dernière chose, db.serverStatus().writeBacksQueued est en fait une métrique qui ne sera jamais différente de zéro dans un environnement fragmenté, et elle doit faire en sorte que les écritures sur un morceau pendant une migration soient traitées correctement (traitées par écouteur d'écriture différée ). Par conséquent, c'est essentiellement un hareng rouge ici - rien à voir avec le volume d'écriture général.

25
Adam C