Principes de dimensionnement

Note de traduction : les Anglais utilisent le terme « scaling » pour la notion de passage à l’échelle et de dimensionnement. Précisons que la problématique dite de passage à l’échelle se présente, en informatique, quand un système donné doit accueillir une charge (une utilisation) très importante. Le système doit alors croître pour fournir le même service à de plus en plus de monde, avec la même qualité (disponibilité, délai, fonctionnalités offertes). Qu’il s’agisse du dimensionnement d’origine, des dimensions à un instant donné, ou de la capacité à croître ou à décroître (à passer à l’échelle), le terme « scaling » (et ses dérivés « scaled, scalable, scalability ») est employé. Certains commentaires ci-après traduits font référence au flou suscité par l’usage d’un même terme.

Passage à l’échelle et dimensionnement sont des termes fourre-tout ; leur faire correspondre une définition précise est difficile. Tout un chacun, du petit frère au chat de la grand-mère, en a sa propre conception. La plupart des définitions sont valables, mais certaines peuvent se contredire. Pis encore ! le terme véhicule des idées fausses. Aussi, pour définir le véritable sens de ces notions, il faut passer le tout à la loupe et extraire, avec une minutie d’horloger, les éléments essentiels.

En premier lieu, le dimensionnement n’implique pas une technique ou technologie particulière. Le passage à l’échelle, ou la capacité à le faire, est une caractéristique d’une architecture donnée. Ce qui est à dimensionner dépend de chaque projet.

Passer à l’échelle, c’est se spécialiser.

—Joe Stump, Architecte en chef de Digg.com et SimpleGeo.com

À travers cette expression, nous pensons que Joe a donné la description la plus fidèle de ce qu’est le passage à l’échelle. Pour autant, elle est insipide, ce qui est inhérent à la notion de dimensionnement. Prenons un exemple. Un site web tel que Facebook.com, avec un très grand nombre d’utilisateurs et de données qui leur sont associés, qui en enregistre chaque jour davantage, voudrait passer à l’échelle les données des utilisateurs qui résident classiquement dans une base de données. À l’opposé, Flickr.com, qui à la base a le même problème que Facebook avec des utilisateurs et des données, voit l’espace occupé par les données (les images) s’accroître bien plus rapidement que le nombre d’utilisateurs. En conséquence, comme les images ne sont pas nécessairement stockées dans des bases de données, le passage à l’échelle du stockage des images est clé pour la croissance de Flickr.

Quand on parle de passage à l’échelle, on pense souvent à l’accroissement. C’est un raccourci néfaste. Le passage à l’échelle engendre aussi le décroissement, c’est-à-dire la capacité à utiliser un nombre réduit de machines lorsque la demande diminue. Nous y reviendrons.

Ce ne sont que deux exemples. Il y en a bien davantage et chacun porte son attention sur un aspect différent. CouchDB est une base de données, aussi nous ne chercherons pas à détailler comment passer à l’échelle n’importe quel système, mais nous nous concentrerons sur ce qui intéresse un utilisateur de CouchDB, c’est-à-dire vous ! Nous avons identifié trois éléments d’importance que vous pouvez passer à l’échelle :

Dimensionner les requêtes de lecture

Une requête de lecture obtient une information de la base de données. Elle se réalise de la manière suivante avec CouchDB : tout d’abord, le module du serveur HTTP doit accepter la requête. Pour ce faire, il ouvre un socket pour y faire transiter les données. L’étape suivante consiste, pour le module de gestion de la requête HTTP, à analyser la requête et à l’envoyer au sous-module CouchDB adapté. Dans le cas d’obtention d’un seul document, la requête est envoyée au module de la base, lequel trouve le document sur le système de fichiers et renvoie la donnée à travers toutes les couches précitées.

Tout cela nécessite du temps de traitement et de disposer d’un nombre suffisant de sockets (ou de descripteurs de fichiers). Le système de stockage du serveur doit être capable de gérer toutes les requêtes de lecture. En outre, il y a d’autres éléments susceptibles de limiter la capacité d’un système à accepter un grand nombre de requêtes de lecture : le principe ici est qu’un serveur ne peut générer que n requêtes de lecture au même moment. Si votre application génère davantage de requêtes, vous avez besoin qu’un autre serveur soit capable de gérer l’excédent.

La caractéristique sympathique des requêtes de lecture est qu’elles peuvent être conservées par un mécanisme d’antémémoire (cached en anglais). Cela permet à une couche de haut niveau d’envoyer la réponse attendue, ce qui soulage votre goulot d’étranglement, lequel se situe au niveau de la recherche du document dans la base. En effet, les requêtes qui pourront profiter de cette antémémoire n’iront pas interroger votre base de données et donc ne coûteront virtuellement rien. Le chapitre 18, Équilibrage de charge détaille ce scénario.

Dimensionner les requêtes d’écriture

Une requête d’écriture est similaire à une requête de lecture, en pire. En effet, elle ne fait pas que lire une donnée sur le disque, elle va écrire une modification de celle-ci. Souvenez-vous que les requêtes de lecture peuvent être antémémorisées ; ce n’est pas le cas des écritures. Par conséquent, il est nécessaire que le mécanisme d’antémémoire soit informé de la modification de la donnée pour qu’il n’envoie pas au client une information périmée. Ou bien les clients doivent recevoir l’ordre de ne pas utiliser l’antémémoire. Si vous avez plusieurs serveurs qui permettent de lire les données, l’écriture doit se produire sur chacun de ces serveurs. Dans tous les cas, votre tâche est considérablement plus difficile quand vous écrivez que quand vous lisez. Le chapitre 19, Groupement de serveurs détaille les méthodes permettant le passage à l’échelle des requêtes d’écriture sur plusieurs serveurs.

Dimensionner les données

La troisième manière de passer à l’échelle est de dimensionner les données. Les disques durs d’aujourd’hui sont peu onéreux et offrent un grand espace de stockage, et cela ne fera que s’améliorer avec le temps. Toutefois, un serveur ne peut décemment gérer qu’un volume limité de données. Il doit maintenir des index, ce qui nécessite de l’espace. La sauvegarde prendra davantage de temps. Les autres tâches d’exploitation deviendront pénibles.

La solution consiste à scinder les données en partitions qui seront faciles à exploiter et à placer chaque tranche sur un serveur distinct. Chaque serveur qui dispose d’une partition fera partie d’un groupement (cluster en anglais) qui détiendra l’ensemble des données. Le chapitre 19, Groupement de serveurs indique comment créer et exploiter ces groupements.

Nous optons pour une approche séparée des opérations de lecture, d’écriture et du partitionnement des données. Toutefois, les décisions prises dans un domaine vont avoir un impact sur les autres. C’est pourquoi nous nous attarderons aussi sur la combinaison de ces approches dans les chapitres suivants.

Prérequis

La réplication est fondamentale pour chacune des méthodes exposées. Avant de vous plonger dans le sujet, le chapitre 16, Réplication vous familiarisera avec l’excellent mécanisme de réplication de CouchDB.