MongoDB et ensembles de données qui ne tiennent pas dans la RAM, peu importe la force de votre effort

12

C'est très dépendant du système, mais les chances sont presque certaines que nous passerons devant une falaise arbitraire et entrerons dans Real Trouble. Je suis curieux de savoir quel type de règles de base existent pour un bon rapport RAM / espace disque. Nous planifions notre prochaine série de systèmes et devons faire des choix concernant la RAM, les SSD et la quantité de chacun des nouveaux nœuds.

Mais maintenant, pour quelques détails sur les performances!

Pendant le flux de travail normal d'une seule exécution de projet, MongoDB est atteint avec un pourcentage très élevé d'écritures (70-80%). Une fois la deuxième étape du pipeline de traitement atteinte, sa lecture est extrêmement élevée car elle doit dédupliquer les enregistrements identifiés dans la première moitié du traitement. C'est le flux de travail pour lequel "garder votre jeu de travail dans la RAM" est fait pour, et nous concevons autour de cette hypothèse.

L'ensemble de données est continuellement frappé par des requêtes aléatoires provenant de sources dérivées de l'utilisateur final; bien que la fréquence soit irrégulière, la taille est généralement assez petite (groupes de 10 documents). Étant donné que cela est destiné à l'utilisateur, les réponses doivent être inférieures au seuil "ennuyé maintenant" de 3 secondes. Ce modèle d'accès est beaucoup moins susceptible d'être dans le cache, il est donc très probable qu'il génère des hits sur le disque.

Un flux de travail de traitement secondaire est une lecture élevée des exécutions de traitement précédentes qui peuvent avoir des jours, des semaines ou même des mois, et il est exécuté rarement mais doit toujours être zippé. Jusqu'à 100% des documents du cycle de traitement précédent seront accessibles. Aucune quantité de réchauffement du cache ne peut aider à cela, je suppose.

La taille des documents finis varie considérablement, mais la taille médiane est d'environ 8 Ko.

La partie haute lecture du traitement de projet normal suggère fortement l'utilisation de répliques pour aider à distribuer le trafic de lecture. J'ai lu ailleurs qu'un RAM-GB 1:10 à HD-GB est une bonne règle de base pour les disques lents, Comme nous envisageons sérieusement d'utiliser des SSD beaucoup plus rapides, je voudrais savoir s'il existe une règle similaire de pouce pour les disques rapides.

Je sais que nous utilisons Mongo d'une manière où le cache-tout ne va vraiment pas voler, c'est pourquoi je cherche des moyens de concevoir un système capable de survivre à une telle utilisation. L' ensemble de données sera probablement la majeure partie d'une tuberculose d'ici six mois et continuera de croître.

sysadmin1138
la source
Une question difficile bien posée.
gWaldo
Il semble que vous allez probablement rencontrer des problèmes de verrouillage en écriture avant de pouvoir régler beaucoup pour IO, honnêtement. Si vous martelez la base de données avec des écritures, vous maintiendrez probablement les verrous en écriture suffisamment longtemps pour que les requêtes soient bloquées quelle que soit la vitesse de l'IO sous-jacent. Quelque chose comme Fusion IO peut réduire un peu le verrouillage en écriture, mais cela prend juste du temps, ce n'est pas une vraie solution.
MrKurt
@MrKurt Une partie de ce que j'essaie de comprendre, c'est quand j'ai besoin de fragmenter, en plus de la façon dont je peux renforcer les nœuds de réplique individuels. Ma spécification provisoire a une carte SSD basée sur PCIe impliquée.
sysadmin1138
Ah, j'ai compris. Vous pourriez envisager le sharding depuis le début, nous faisons beaucoup de sharding sur un seul serveur. Il vous permet de contourner le verrouillage d'écriture et de mettre à l'échelle efficacement les écritures sur le nombre total de cœurs. De plus, il est facile de déplacer des fragments entre les serveurs ultérieurement.
MrKurt

Réponses:

5

Ce sera un tas de petits points. Il n'y a malheureusement pas de réponse unique à votre question.

MongoDB permet au noyau du système d'exploitation de gérer la gestion de la mémoire. En plus de jeter autant de RAM que possible sur le problème, il n'y a que peu de choses qui peuvent être faites pour «gérer activement» votre ensemble de travail.

La seule chose que vous pouvez faire pour optimiser les écritures est de rechercher d'abord cet enregistrement (faire une lecture), afin qu'il soit dans la mémoire de travail. Cela évitera les problèmes de performances associés au verrouillage global à l'échelle du processus (qui est censé devenir per-db dans la v2.2)

Il n'y a pas de règle stricte pour le rapport RAM vs SSD, mais je pense que les IOPS bruts des SSD devraient vous permettre d'aller avec un rapport beaucoup plus faible. Du haut de ma tête, 1: 3 est probablement le plus bas avec lequel vous voulez aller. Mais étant donné les coûts plus élevés et les capacités plus faibles, vous devrez probablement maintenir ce ratio de toute façon.

En ce qui concerne les «phases d'écriture et de lecture», est-ce que je lis correctement qu'une fois qu'un enregistrement est écrit, il est rarement mis à jour («renversé»)? Si tel est le cas, il peut être intéressant d'héberger deux clusters; le cluster d'écriture normal et le cluster optimisé en lecture pour les données « anciennes » qui n'ont pas été modifiées dans [X période] . Je voudrais certainement activer la lecture esclave sur ce cluster. (Personnellement, je gérerais cela en incluant une valeur de date modifiée dans les documents d'objet de votre base de données.)

Si vous avez la possibilité de tester la charge avant d'entrer dans Prod, surveillez-en parfaitement. MongoDB a été écrit avec l'hypothèse qu'il serait souvent déployé dans des machines virtuelles (leurs systèmes de référence sont dans EC2), alors n'ayez pas peur de les répartir sur des machines virtuelles.

gWaldo
la source
Pendant le traitement, un talon de document initial est créé et est ensuite continuellement mis à jour par différentes sous-étapes dans la première partie du traitement. Nous avons soupesé la possibilité de faire un peu de rembourrage manuel sur la création initiale pour réduire la quantité d'extension que nous faisons, mais notre pourcentage de verrouillage en écriture actuel est heureusement bas.
sysadmin1138
Le conseil de lire un enregistrement avant de lui écrire pour le mettre en RAM n'est pas un bon conseil. Depuis la version 2.0 (mi-2011), MongoDB a eu un rendement si les données accessibles ne sont pas en RAM, donc vous causez simplement une lecture supplémentaire et un aller-retour supplémentaire vers le serveur sans aucune bonne raison si vous le faites car le verrou ne le ferait pas ne sera pas détenu pour cette durée de toute façon.
Asya Kamsky
13

Ceci est destiné à être un addendum aux autres réponses publiées ici, qui discutent de nombreux éléments pertinents à considérer ici. Cependant, il existe un autre facteur, souvent ignoré, en ce qui concerne l'utilisation efficace de la RAM dans un système de type à accès aléatoire - la lecture anticipée.

Vous pouvez vérifier les paramètres actuels de lecture anticipée (sous Linux) en exécutant blockdev --report(nécessite généralement les privilèges sudo / root). Cela imprimera un tableau avec une ligne pour chaque périphérique de disque. La colonne RA contient la valeur de readahead. Cette valeur est le nombre de secteurs de 512 octets (à moins que la taille du secteur ne soit pas la valeur par défaut - notez qu'au moment de la rédaction de cet article, même les disques qui ont des tailles plus grandes sont traités comme des secteurs de 512 octets par le noyau) qui sont lus tous les accès au disque.

Vous pouvez définir le paramètre de lecture anticipée pour un périphérique de disque donné en exécutant:

blockdev --setra <value> <device name>

Lorsque vous utilisez un système RAID logiciel, assurez-vous de définir la lecture anticipée sur chaque périphérique de disque ainsi que sur le périphérique correspondant au contrôleur RAID.

Pourquoi est-ce important? Eh bien, readahead utilise la même ressource que MongoDB essaie d'utiliser afin d'optimiser vos lectures pour un accès séquentiel - la RAM. Lorsque vous effectuez des lectures séquentielles sur des disques en rotation (ou des appareils qui se comportent de toute façon comme des disques en rotation - EBS, je vous regarde), la récupération des données à proximité dans la RAM peut augmenter considérablement les performances, vous faire économiser sur les recherches et un paramètre de lecture anticipée élevé dans le bon environnement peut vous donner des résultats impressionnants.

Pour un système comme MongoDB où votre accès sera généralement un accès aléatoire sur un ensemble de données, cela gaspille simplement de la mémoire qui est mieux utilisée ailleurs. Le système, qui, comme mentionné ailleurs, gère également la mémoire pour MongoDB, va allouer un morceau de mémoire à la lecture anticipée quand il est demandé et donc laisser moins de RAM pour que MongoDB puisse l'utiliser efficacement.

Choisir la bonne taille de lecture anticipée est délicat et dépend de votre matériel, de la configuration, de la taille des blocs, de la taille des bandes et des données elles-mêmes. Si vous passez aux SSD par exemple, vous voudrez un réglage bas, mais le niveau bas dépendra des données.

Pour expliquer: vous voulez vous assurer que la lecture anticipée est suffisamment élevée pour extraire un document unique complet et ne pas avoir à revenir sur le disque. Prenons votre taille médiane mentionnée de 8k - puisque les secteurs sur le disque sont généralement de 512 octets, il faudrait 16 accès au disque pour lire dans le document entier sans lecture anticipée. Si vous aviez une lecture anticipée de 16 secteurs ou plus, vous liriez tout le document avec un seul voyage sur le disque.

En fait, étant donné que les compartiments d'index MongoDB sont de 8 Ko, vous ne voudrez jamais définir la lecture anticipée en dessous de 16 de toute façon, ou il faudra 2 accès au disque pour lire dans un compartiment d'index. Une bonne pratique générale consiste à commencer par votre paramètre actuel, à le diviser par deux, puis à réévaluer votre utilisation de RAM et d'E / S et à partir de là.

Adam C
la source
1
Des informations précieuses qui vous seront certainement utiles une fois que nous aurons du matériel en interne. Merci!
sysadmin1138
3

Vous devriez envisager d'utiliser des répliques pour les requêtes des utilisateurs finaux et de faire exécuter votre flux de travail sur d'autres machines.

En utilisant votre règle empirique 1:10, vous regardez environ 128 Go de RAM pour 1 To de stockage sur disque; Alors que certains SSD abordables prétendent aujourd'hui atteindre> 60K IOPS, les chiffres réels peuvent différer un peu, ainsi que si vous utilisez RAID avec vos SSD ou non, et si vous l'êtes, la carte RAID est également extrêmement importante .

Au moment de ce billet, passer de 128 Go de RAM DDR3 ECC à 256 Go semble représenter environ 2000 $ de plus sur un serveur Intel 1U, et cela vous donnera un rapport 1: 5 avec 1 To de données, ce qui, à mon avis, serait un rapport encore meilleur. Si vous avez besoin que votre charge de travail soit terminée le plus rapidement possible, davantage de RAM vous aidera certainement, mais est-ce vraiment si urgent?

Vous devrez également effectuer un ajustement du système de fichiers, quelque chose comme "noatime, data = writeback, nobarrier" sur ext4, et vous devrez peut-être également effectuer quelques ajustements des paramètres du noyau pour tirer le meilleur parti des performances de votre système.

Si vous optez pour le RAID, le RAID-10 sera un très bon choix, et avec le contrôleur RAID approprié offrira une amélioration des performances, mais avec une réduction de moitié de votre espace disponible. Vous pouvez également vous pencher sur RAID50 si vous voulez une amélioration des performances décente sans réduire de moitié votre espace disponible. Le risque d'exécuter un RAID est que vous n'avez plus accès à TRIM sur vos disques, ce qui signifie que vous devez de temps en temps déplacer vos données, casser le RAID, TRIM les disques et recréer le RAID.

En fin de compte, vous devez décider de la complexité que vous souhaitez, du montant que vous souhaitez dépenser et de la rapidité avec laquelle vous souhaitez traiter votre charge de travail. J'évaluerais également si MongoDB est la base de données idéale à utiliser, car vous pouvez toujours utiliser Mongo pour les requêtes des utilisateurs finaux qui nécessitent des réponses rapides, mais utilisez autre chose pour traiter vos données, qui n'ont pas besoin d'être prêtes en quelques secondes , et cela peut également vous permettre de répartir votre charge de travail sur plusieurs machines avec plus de facilité.

gekkz
la source