Discord, la plateforme de communication prisée par des millions d’utilisateurs, a partagé les détails fascinants de l’évolution de son infrastructure de recherche. Cette dernière lui permet aujourd’hui d’indexer des trillions de messages tout en introduisant de nouvelles fonctionnalités, comme la recherche multi-serveurs. Cet article plonge dans les rouages techniques de cette transformation, en s’inspirant de l’article original publié sur le blog de Discord.
Contexte et problèmes initiaux
En 2017, Discord a déployé son premier système de recherche pour indexer des milliards de messages. À cette époque, l’infrastructure reposait sur Elasticsearch, un moteur de recherche open-source puissant et flexible. Les messages étaient organisés – ou shardés – par serveur (appelé guild dans le jargon de Discord) ou par message direct (DM). Chaque shard était stocké dans des indices répartis sur deux clusters Elasticsearch. Cette organisation permettait de regrouper les messages d’un même serveur pour accélérer les recherches tout en maintenant des clusters de taille gérable.
Pour économiser des ressources, Discord utilisait une indexation paresseuse (lazy indexing). Concrètement, les messages n’étaient indexés que lorsqu’un utilisateur lançait une recherche dans un serveur pour la première fois. Une file d’attente basée sur Redis servait d’intermédiaire : elle stockait les messages à indexer, et des workers (processus en arrière-plan) les récupéraient par lots pour les envoyer à Elasticsearch. Cette approche tirait parti des capacités d’indexation en masse (bulk indexing) d’Elasticsearch, qui permet de traiter plusieurs documents en une seule opération.
Mais avec la croissance explosive de Discord – des millions de nouveaux utilisateurs et des serveurs toujours plus grands – cette architecture a révélé ses limites :
- Perte de messages dans Redis : Redis, bien qu’extrêmement rapide pour les opérations en mémoire, n’était pas conçu pour garantir la livraison des messages dans des scénarios à haute disponibilité. En cas de surcharge ou de panne, des messages pouvaient être perdus.
- Surcharge des nœuds Elasticsearch : L’indexation en masse, bien qu’efficace, pouvait submerger les nœuds Elasticsearch, surtout lorsque des milliers de messages devaient être traités simultanément.
- Hotspots dus aux grands serveurs : Les serveurs populaires, avec des millions de membres et un flot constant de messages, généraient un trafic disproportionné. Cela créait des hotspots – des points chauds où un nœud ou un shard était surchargé – ralentissant l’ensemble du système.
Ces défis ont poussé Discord à repenser son infrastructure pour la rendre plus robuste, scalable et capable de supporter une croissance continue.
Migration de la file d’attente vers Google Cloud PubSub
Le premier problème à résoudre était la fiabilité de la file d’attente. Redis, bien qu’adapté à des tâches simples et rapides, ne pouvait pas garantir la livraison des messages dans un environnement aussi exigeant que celui de Discord. Pour y remédier, l’équipe a migré la file d’attente vers Google Cloud PubSub, un service de messagerie cloud conçu pour gérer des volumes massifs de données avec une disponibilité maximale.
Pourquoi PubSub ?
- Livraison garantie : Contrairement à Redis, PubSub stocke les messages de manière persistante et les redélivre en cas d’échec, éliminant ainsi les pertes de données.
- Scalabilité automatique : PubSub s’adapte aux pics de charge sans intervention manuelle, un atout crucial pour une plateforme en croissance rapide comme Discord.
- Intégration fluide : L’équipe a pu intégrer PubSub dans son architecture existante avec des modifications minimales, accélérant la transition.
Exemple concret
Imaginez une file d’attente comme une boîte aux lettres. Avec Redis, si le facteur (le worker) arrive alors que la boîte déborde, des lettres (messages) peuvent être perdues. Avec PubSub, chaque lettre est enregistrée et conservée jusqu’à ce que le facteur la prenne en charge, même en cas de retard ou de panne.
Cette migration a résolu les pertes de messages et a posé les bases pour d’autres améliorations, tout en ouvrant la porte à de nouveaux cas d’utilisation, comme la planification de tâches complexes.
Amélioration de l’indexation en masse
L’indexation en masse est une fonctionnalité clé d’Elasticsearch : elle permet de traiter des milliers de messages en une seule requête, réduisant ainsi la charge sur le système. Cependant, dans l’approche initiale de Discord, les workers récupéraient des lots de messages sans se soucier de leur destination finale – c’est-à-dire le cluster et l’index Elasticsearch où ils devaient être stockés. Résultat : une opération d’indexation pouvait toucher plusieurs nœuds simultanément, augmentant le risque de surcharge ou d’échec.
Pour optimiser ce processus, Discord a introduit un routeur PubSub, une couche intermédiaire intelligente qui :
- Récupère les messages depuis PubSub.
- Les regroupe par cluster et index de destination.
- Envoie des lots cohérents au bon cluster Elasticsearch.
Avantages
- Charge réduite : Chaque opération d’indexation ne concerne qu’un seul nœud, évitant les surcharges inutiles.
- Isolation des pannes : Si un nœud tombe en panne, seules les opérations qui lui sont destinées sont affectées, et non l’ensemble du système.
- Performance accrue : Les lots sont plus ciblés, ce qui accélère le traitement.
Une analogie
Pensez à une cuisine de restaurant. Avant, les serveurs apportaient des commandes mélangées à tous les chefs en même temps, créant le chaos. Maintenant, un maître d’hôtel (le routeur) trie les commandes et les distribue au bon chef (nœud), rendant la préparation plus fluide.
Cette amélioration a été cruciale pour gérer un nombre croissant de clusters et d’indices, tout en maintenant une indexation rapide et fiable.
Introduction des cellules Elasticsearch
Pour aller plus loin dans la scalabilité, Discord a introduit le concept de cellules. Une cellule est un regroupement logique de plusieurs petits clusters Elasticsearch, chacun dédié à une portion spécifique des données.
Pourquoi des cellules ?
- Distribution de la charge : Les messages de différents serveurs sont répartis sur plusieurs clusters, évitant les hotspots.
- Isolation des grands serveurs : Un serveur avec des millions de messages peut être isolé dans sa propre cellule, protégeant ainsi les performances des autres utilisateurs.
- Maintenance simplifiée : Une cellule peut être mise à jour ou réparée sans affecter l’ensemble du système.
Impact
Cette structure a permis à Discord de gérer des volumes de données massifs tout en débloquant des fonctionnalités avancées. Par exemple, la recherche multi-serveurs – qui permet de chercher dans plusieurs serveurs à la fois – repose sur cette capacité à répartir et coordonner les données efficacement.
Imaginez une bibliothèque : au lieu d’avoir un seul rayonnage géant pour tous les livres, vous avez plusieurs petites sections (cellules). Si une section devient trop populaire, elle peut être déplacée ou agrandie sans perturber le reste.
Architecture des clusters et des nœuds
Au sein de chaque cluster d’une cellule, Discord a adopté une architecture avec des nœuds dédiés, chacun optimisé pour une tâche spécifique :
- Nœuds d’ingestion : Ils prétraitent et routent les messages. Sans état (stateless), ils peuvent être facilement multipliés pour absorber les pics de charge.
- Nœuds maîtres éligibles : Responsables de la coordination du cluster, ils disposent de ressources dédiées pour garantir la stabilité.
- Nœuds de données : Ils stockent les messages indexés et exécutent les requêtes. Configurés avec une mémoire suffisante (heap), ils supportent les opérations intensives.
Pourquoi cette séparation ?
Cette spécialisation permet d’allouer les ressources là où elles sont nécessaires. Par exemple, un nœud d’ingestion n’a pas besoin de stocker des données, il peut donc être léger et rapide, tandis qu’un nœud de données doit être robuste pour gérer des indices volumineux.
Les pods (instances) de ces nœuds sont déployés sur des machines et des nodepools distincts dans Kubernetes, optimisant encore davantage l’utilisation des ressources.
Déploiement dans Kubernetes
Pour orchestrer cette infrastructure complexe, Discord a migré ses clusters Elasticsearch vers Kubernetes, un système d’orchestration de conteneurs. Kubernetes offre :
- Automatisation : Déploiement, mise à l’échelle et gestion des pods sont automatisés.
- Résilience : En cas de panne, Kubernetes redémarre ou remplace les pods défaillants.
- Optimisation : Les ressources sont allouées précisément grâce aux nodepools.
Exemple
Si un cluster est comme une équipe de travailleurs, Kubernetes est le chef d’orchestre qui assigne les tâches, remplace les absents et s’assure que tout fonctionne harmonieusement.
Cette transition a réduit la charge opérationnelle pour les équipes de Discord tout en améliorant la fiabilité de l’infrastructure.
Bénéfices et nouvelles fonctionnalités
Ces évolutions ont apporté des améliorations significatives :
- Indexation fiable : Avec PubSub et le routage optimisé, les messages sont indexés sans perte et plus rapidement.
- Gestion des grands serveurs : Les cellules isolent les serveurs à fort trafic, éliminant les hotspots.
- Scalabilité : Le système supporte des trillions de messages sans compromettre les performances.
- Nouvelles fonctionnalités : La recherche multi-serveurs, par exemple, est désormais possible grâce à cette architecture flexible.
Ces changements ne se limitent pas à des gains techniques : ils améliorent directement l’expérience des utilisateurs, rendant la recherche plus rapide et plus puissante.
L’évolution de l’infrastructure de recherche de Discord illustre parfaitement comment une entreprise technologique peut relever les défis de la croissance. En migrant vers Google Cloud PubSub, en optimisant l’indexation, en introduisant des cellules Elasticsearch et en adoptant Kubernetes, Discord a transformé un système limité en une architecture capable de gérer des trillions de messages.
Cette transformation montre l’importance d’adapter constamment les technologies aux besoins changeants. Pour Discord, cela signifie offrir une expérience fluide à des millions d’utilisateurs tout en posant les bases pour de futures innovations.
Source : Cet article est basé sur « How Discord Indexes Trillions of Messages », publié sur le blog de Discord.