Dans le domaine des bases de données distribuées, Apache Cassandra est un acteur important. Il offre un mélange d'évolutivité robuste et de haute disponibilité sans compromettre les performances. Cependant, Cassandra est également réputé pour être difficile à régler en termes de performances et pour les pièges qui peuvent survenir au cours de ce processus. La grande flexibilité du système, bien qu'elle soit un atout majeur, signifie également que l'exploitation efficace de toutes ses capacités implique souvent de naviguer dans un labyrinthe complexe de configurations et de compromis en matière de performances. Si elle n'est pas gérée avec soin, cette complexité peut parfois entraîner des comportements inattendus ou des performances sous-optimales.
Dans cet article de blog, nous parcourons le parcours d'optimisation Cassandra de DoorDash. Je partagerai ce que nous avons appris en rendant notre flotte beaucoup plus performante et rentable. En analysant nos cas d'utilisation, nous espérons partager des leçons universelles que vous pourriez trouver utiles. Avant de plonger dans les détails, parlons brièvement des bases de Cassandra et de ses avantages et inconvénients en tant que base de données NoSQL distribuée.
Qu'est-ce qu'Apache Cassandra ?
Apache Cassandra est un système de gestion de base de données NoSQL distribué et open-source, conçu pour gérer de grandes quantités de données sur un large éventail de serveurs de base. Il offre une haute disponibilité sans point de défaillance unique. Fortement inspiré par DynamoDB d'Amazon en 2007, Facebook a développé Cassandra pour alimenter sa fonction de recherche dans la boîte de réception, puis l'a mise en open-source. Depuis lors, il est devenu l'un des magasins de valeurs clés distribués préférés.
Cassandra pros
- Évolutivité: L'une des caractéristiques les plus convaincantes de Cassandra est son exceptionnelle évolutivité. Il excelle dans la mise à l'échelle horizontale et verticale, ce qui lui permet de gérer de grands volumes de données sans effort.
- Tolérance aux pannes: Cassandra offre une excellente tolérance aux pannes grâce à son architecture distribuée. Les données sont répliquées sur plusieurs nœuds, ce qui garantit qu'il n'y a pas de point de défaillance unique.
- Haute disponibilité: Grâce à sa stratégie de réplication et à sa nature décentralisée, Cassandra garantit une haute disponibilité, ce qui en fait un choix fiable pour les applications critiques.
- Flexibilité: Cassandra prend en charge une conception flexible des schémas, ce qui est une aubaine pour les applications dont les structures de données évoluent.
- Efficacité en écriture: Cassandra est optimisé pour un débit d'écriture élevé, gérant sans problème de gros volumes d'écriture.
Cassandra cons
- Performances en lecture: Si Cassandra excelle en matière d'efficacité d'écriture, ses performances de lecture peuvent être moins impressionnantes, en particulier dans les scénarios impliquant de grands ensembles de données avec des lectures fréquentes et des contraintes de cohérence élevées.
- La modification des données est coûteuse: Cassandra étant un arbre de fusion structuré en logs où les données écrites sont immuables, les suppressions et les mises à jour sont coûteuses. Les suppressions, en particulier, peuvent générer des pierres tombales qui ont un impact sur les performances. Si votre charge de travail est fortement axée sur les suppressions et les mises à jour, une architecture basée uniquement sur Cassandra n'est peut-être pas le meilleur choix.
- Complexité des réglages: Le réglage de Cassandra pour des performances optimales nécessite une compréhension approfondie de ses mécanismes internes, ce qui peut être complexe et prendre du temps.
- Compromis de cohérence: conformément au théorème CAP, Cassandra sacrifie souvent la cohérence au profit de la disponibilité et de la tolérance à la partition, ce qui peut ne pas convenir à tous les cas d'utilisation.
Les nuances de Cassandra
Les nuances entourant l'application de Cassandra deviennent évidentes lorsque l'on évalue ses avantages par rapport aux exigences d'un cas d'utilisation spécifique. Bien que son évolutivité et sa fiabilité soient inégalées pour les applications à forte intensité d'écriture, il faut tenir compte de la nature des données et des schémas d'accès de son projet. Par exemple, si votre application nécessite des capacités d'interrogation complexes, des systèmes comme MongoDB pourraient être plus appropriés. En revanche, si la cohérence est une exigence essentielle, CockroachDB pourrait être mieux adapté.
Chez DoorDash, nous avons traversé ces zones grises en évaluant soigneusement nos besoins et en les alignant sur les capacités de Cassandra. Nous avons reconnu qu'aucun système n'est une solution universelle, mais qu'avec un réglage méticuleux et une bonne compréhension, le potentiel de Cassandra pouvait être maximisé pour répondre à nos attentes et même les dépasser. Les sections suivantes expliquent comment nous avons abordé le réglage de Cassandra - en atténuant ses inconvénients tout en exploitant ses avantages - afin de l'adapter efficacement à nos cas d'utilisation intensifs en données.
Restez informé grâce aux mises à jour hebdomadaires
Abonnez-vous à notre blog d'ingénierie pour recevoir régulièrement des informations sur les projets les plus intéressants sur lesquels notre équipe travaille.
Please enter a valid email address.
Merci de vous être abonné !
Oser s'améliorer
En raison de la croissance rapide de DoorDash, notre utilisation de Cassandra a augmenté rapidement. Malgré l'amélioration de notre vitesse de développement, cette croissance rapide a laissé une trace d'opportunités manquées pour affiner les performances de Cassandra. Afin de saisir certaines de ces opportunités, l'équipe Infrastructure Storage a travaillé en étroite collaboration avec les équipes produits sur un projet d'optimisation qui a duré plusieurs mois. Le projet a permis d'obtenir des résultats étonnants, notamment :
- ~35% de réduction des coûts pour l'ensemble de la flotte Cassandra
- Pour chaque dollar dépensé, nous sommes en mesure de traiter 59 Ko de données par seconde contre 23 Ko, soit une amélioration considérable de 154 % de l'économie unitaire.
Dans la section suivante, nous examinerons des exemples spécifiques de notre flotte qui peuvent s'appliquer à d'autres cas d'utilisation.
Concevez votre schéma de manière judicieuse dès le départ
L'étape fondamentale pour garantir un cluster Cassandra optimisé est d'avoir un schéma bien conçu. Les choix de conception effectués au niveau du schéma ont des répercussions considérables sur les performances, l'évolutivité et la maintenabilité. Un schéma mal conçu dans Cassandra peut entraîner des problèmes tels que des requêtes inefficaces, des points chauds dans la distribution des données et des difficultés de mise à l'échelle. Voici quelques éléments clés à prendre en compte pour concevoir un schéma Cassandra efficace :
- Comprendre les schémas d'accès aux données: Avant de concevoir votre schéma, il est essentiel de bien comprendre les schémas d'accès aux données de votre application. Cassandra est optimisé pour des écritures rapides et des lectures efficaces, mais seulement si le modèle de données s'aligne sur la façon dont les données seront accédées. Concevez vos tables en fonction de vos requêtes, et non l'inverse.
- Utilisation efficace des clés primaires: La clé primaire dans Cassandra est composée de clés de partition et de colonnes de clustering. La clé de partition détermine la distribution des données dans le cluster, il est donc essentiel de choisir une clé de partition qui assure une distribution homogène des données tout en prenant en charge vos schémas d'accès principaux. Les colonnes de regroupement déterminent l'ordre de tri au sein d'une partition et peuvent être utilisées pour prendre en charge des requêtes de plage efficaces.
- Évitez les grandes partitions: Des partitions extrêmement grandes peuvent nuire aux performances de Cassandra. Elles peuvent entraîner des problèmes tels que de longues pauses de collecte de déchets, des latences de lecture accrues et des difficultés de compactage. Concevez votre schéma de manière à éviter les points chauds et à garantir une distribution plus uniforme des données.
- Normalisation et dénormalisation: Contrairement aux systèmes traditionnels de gestion de bases de données relationnelles (SGBDR), Cassandra n'excelle pas dans l'assemblage de tables. Par conséquent, la dénormalisation est souvent nécessaire. Cependant, il s'agit d'un équilibre ; alors que la dénormalisation peut simplifier les requêtes et améliorer les performances, elle peut également conduire à la redondance des données et à des besoins de stockage plus importants. Réfléchissez bien à votre cas d'utilisation lorsque vous décidez de l'ampleur de la dénormalisation.
- Considérez les implications des index secondaires: Les index secondaires dans Cassandra peuvent être utiles, mais ils sont assortis de compromis. Ils peuvent ajouter de la surcharge et ne sont pas toujours efficaces, en particulier si les colonnes indexées ont une cardinalité élevée ou si les modèles de requête n'exploitent pas les points forts des index secondaires.
- TTL et gestion des pierres tombales: Le Time-to-live, ou TTL, est une fonctionnalité puissante de Cassandra qui permet de gérer l'expiration des données. Cependant, il est important de comprendre comment le TTL et les tombstones qui en résultent affectent les performances. Une mauvaise gestion des tombstones peut entraîner une dégradation des performances au fil du temps. Dans la mesure du possible, évitez les suppressions.
- Stratégies de mise à jour: Comprendre le fonctionnement des mises à jour dans Cassandra. Les mises à jour étant essentiellement des opérations d'écriture, elles peuvent entraîner la création de plusieurs versions d'une ligne qui doivent être résolues au moment de la lecture, ce qui a un impact sur les performances. Concevez vos modèles de mise à jour de manière à minimiser ces impacts. Si possible, évitez les mises à jour.
Choisissez judicieusement votre niveau de cohérence
La capacité de Cassandra à configurer les niveaux de cohérence pour les opérations de lecture et d'écriture offre un outil puissant pour équilibrer la précision des données et les performances. Cependant, comme toute fonctionnalité puissante, elle s'accompagne d'une mise en garde : la responsabilité. Le niveau de cohérence choisi peut avoir un impact significatif sur les performances, la disponibilité et la tolérance aux pannes de votre cluster Cassandra, notamment dans les domaines suivants :
- Comprendre les niveaux de cohérence: Dans Cassandra, les niveaux de cohérence vont de ONE (où l'opération nécessite la confirmation d'un seul nœud) à ALL (où l'opération nécessite l'acquittement de toutes les répliques du cluster). Il existe également des niveaux tels que QUORUM (nécessitant une majorité de nœuds) et LOCAL_QUORUM (une majorité au sein du centre de données local). Chacun de ces niveaux a ses propres implications sur les performances et la précision des données. Vous pouvez en savoir plus sur ces niveaux dans les configurations ici.
- Compromis entre performance et précision : Les niveaux de cohérence inférieurs tels que ONE peuvent offrir une meilleure performance car ils nécessitent moins de nœuds pour répondre. Cependant, ils comportent également un risque plus élevé d'incohérence des données. Les niveaux plus élevés, comme ALL, garantissent une forte cohérence, mais peuvent avoir un impact significatif sur les performances et la disponibilité, en particulier dans une configuration multi-centres de données.
- Impact sur la disponibilité et la tolérance aux pannes: Des niveaux de cohérence plus élevés peuvent également avoir un impact sur la disponibilité de votre application. Par exemple, si vous utilisez un niveau de cohérence ALL et qu'une seule réplique est en panne, l'opération échouera. Il est donc important de trouver un équilibre entre le besoin de cohérence et le risque de défaillance des nœuds et de problèmes de réseau.
- Ajustement dynamique en fonction du cas d'utilisation : Une stratégie consiste à ajuster dynamiquement les niveaux de cohérence en fonction de la criticité de l'opération ou de l'état actuel du cluster. Cette approche nécessite une logique d'application plus sophistiquée mais peut optimiser à la fois les performances et la précision des données.
Ajustez votre stratégie de compactage (et votre filtre Bloom)
Le compactage est un processus de maintenance dans Cassandra qui fusionne plusieurs SSTables, ou tables de chaînes triées, en une seule. Le compactage est effectué pour récupérer de l'espace, améliorer les performances de lecture, nettoyer les tombstones et optimiser les E/S disque.
Les utilisateurs doivent choisir entre trois stratégies principales pour déclencher le compactage dans les utilisateurs de Cassandra en fonction de leurs cas d'utilisation. Chaque stratégie est optimisée pour différentes choses :
- Stratégie de compactage en fonction de la taille, ou STCS
- Mécanisme de déclenchement :
- La stratégie surveille la taille des tables SST. Lorsqu'un certain nombre d'entre elles atteignent à peu près la même taille, le processus de compactage est déclenché pour ces tables. Par exemple, si le système a un seuil fixé à quatre, lorsque quatre tables SST atteignent une taille similaire, elles sont fusionnées en une seule au cours du processus de compactage.
- Quand l'utiliser ?
- Charges de travail à forte intensité d'écriture
- Tailles cohérentes des tables SST
- Pour :
- Amplification réduite de l'écriture
- Bonne performance en matière d'écriture
- Cons :
- Baisse potentielle des performances de lecture en raison de l'augmentation du nombre de balayages de la table SSTable
- Fusionne les données anciennes et nouvelles au fil du temps
- Pour que cette stratégie de compactage soit efficace, vous devez laisser un disque de réserve beaucoup plus grand.
- Mécanisme de déclenchement :
- Stratégie de compactage nivelé (LCS)
- Mécanisme de déclenchement :
- Les données sont organisées en niveaux. Le niveau 0 (L0) est spécial et contient les tables SST qui viennent d'être vidées ou compactées. Lorsque le nombre de tables SST dans L0 dépasse un seuil spécifique (par exemple 10 tables SST), ces tables SST sont compactées avec les tables SST du niveau 1 (L1). Lorsque L1 dépasse sa taille limite, il est compacté avec L2, et ainsi de suite.
- Quand l'utiliser ?
- Charges de travail à forte intensité de lecture
- Besoin de performances de lecture constantes
- La gestion de l'espace disque est essentielle
- Pour :
- Performances de lecture prévisibles grâce à un nombre réduit de tables SST.
- Utilisation efficace de l'espace disque
- Cons :
- Amplification accrue de l'écriture
- Mécanisme de déclenchement :
- Stratégie de compactage TimeWindow, ou TWCS
- Mécanisme de déclenchement :
- Les tables SST sont regroupées en fonction de l'horodatage des données, ce qui permet de créer des fenêtres temporelles distinctes, par exemple quotidiennes ou horaires. Lorsqu'une fenêtre temporelle expire - ce qui signifie que nous sommes passés à la fenêtre suivante - les SSTables de cette fenêtre expirée deviennent des candidats au compactage. Seules les tables SST situées dans la même fenêtre sont compactées ensemble, ce qui garantit la localité temporelle des données.
- Quand l'utiliser ?
- Données chronologiques ou données prévisibles sur le cycle de vie
- Expirations basées sur TTL
- Pour :
- Traitement efficace des données de séries temporelles
- Amplification réduite de la lecture pour les requêtes horodatées
- SSTables immuables plus anciennes
- Cons :
- Ne convient pas aux charges de travail non temporelles
- Problèmes d'espace potentiels si les données d'une fenêtre temporelle sont très nombreuses et varient considérablement d'une fenêtre à l'autre.
- Mécanisme de déclenchement :
D'après notre expérience, à moins que vous ne stockiez strictement des données de séries temporelles avec un TTL prédéfini, LCS devrait être votre choix par défaut. Même si votre application est gourmande en écriture, l'espace disque supplémentaire requis par des SSTables de plus en plus grandes sous STCS rend cette stratégie peu attrayante. Le LCS est une évidence dans les cas d'utilisation intensive en lecture. La figure 2 ci-dessous montre la baisse de l'utilisation du disque après avoir changé de stratégie de compactage et de nettoyage.
Il est facile d'oublier que chaque stratégie de compactage doit avoir une taille de cache différente pour le filtre Bloom. Lorsque vous passez d'une stratégie de compactage à l'autre, n'oubliez pas d'ajuster cette taille de cache en conséquence.
- Paramètre par défaut du filtre Bloom de STCS : Le paramètre par défaut de STCS vise généralement un équilibre entre l'utilisation de la mémoire et les performances de lecture. Parce que STCS peut conduire à des SSTables plus grandes, le filtre bloom peut être configuré comme légèrement plus grand que ce qui serait utilisé dans LCS pour réduire le risque de lectures inutiles sur le disque. Cependant, la taille exacte dépendra de la configuration de Cassandra et de la charge de travail spécifique.
- Paramètre par défaut du filtre de Bloom du LCS : Les filtres Bloom de LCS sont généralement plus petits parce que les tables SST sont gérées par niveaux et que chaque niveau contient des données qui ne se chevauchent pas. Cette organisation réduit la nécessité d'utiliser des filtres plus grands, car il est moins probable que des lectures inutiles soient effectuées sur le disque.
- Paramètre par défaut du filtre Bloom de TWCS : Utilisé principalement pour les données de séries temporelles, TWCS implique généralement des SSTables à durée de vie plus courte en raison de la nature de l'expiration des données basée sur le temps. La taille par défaut du filtre Bloom pour TWCS peut être ajustée pour refléter la nature temporelle des données ; elle est potentiellement plus petite en raison du vieillissement prévisible des SSTables.
À titre d'exemple, nous avons fait passer l'un de nos clusters Cassandra fonctionnant sous la version 3.11 de STCS à LCS, comme le montre la figure 3 ci-dessous. Cependant, nous n'avons pas augmenté la taille du cache du filtre Bloom en conséquence. Par conséquent, les nœuds de cette grappe manquaient constamment de mémoire, ou OOM, en raison de l'augmentation du taux de faux positifs pour les lectures. Après avoir augmenté bloom_filter_fp_chance de 0,01 à 0,1, beaucoup plus de mémoire OS est épargnée, ce qui élimine le problème de l'OOM.
Mettre en lot ou ne pas mettre en lot ? Une question difficile
Dans les bases de données relationnelles traditionnelles, la mise en lots des opérations est une technique courante pour améliorer les performances, car elle permet de réduire les allers-retours sur le réseau et de rationaliser la gestion des transactions. Cependant, lorsqu'on travaille avec une base de données distribuée comme Cassandra, l'approche de la mise en lots, que ce soit pour les lectures ou les écritures, doit être soigneusement étudiée en raison de son architecture unique et de ses méthodes de distribution des données.
Écritures en lots : Les compromis
Cassandra, optimisé pour un débit d'écriture élevé, traite efficacement les opérations d'écriture individuelles sur ses nœuds distribués. Mais les écritures par lots, au lieu d'améliorer les performances, peuvent introduire plusieurs défis, tels que :
- Augmentation de la charge sur les nœuds coordinateurs : Les lots importants peuvent créer des goulets d'étranglement au niveau du nœud coordinateur, qui est chargé de gérer la distribution de ces opérations d'écriture.
- Amplification de l'écriture : La mise en lots peut entraîner l'écriture de plus de données que nécessaire sur le disque, ce qui met à rude épreuve le sous-système d'entrées/sorties.
- Risque de latence et de défaillance : Les opérations par lots importants peuvent dépasser les seuils de temporisation, ce qui entraîne des écritures partielles ou la nécessité d'effectuer de nouvelles tentatives.
Compte tenu de ces facteurs, nous estimons souvent que des lots plus petits et plus fréquents ou des écritures individuelles sont plus efficaces, garantissant une répartition plus équilibrée de la charge et des performances constantes.
Lectures groupées : Une perspective différente
Les lectures par lots dans Cassandra, ou opérations multi-get, impliquent la récupération de données à partir de plusieurs lignes ou partitions. Bien qu'apparemment efficace, cette approche s'accompagne de son lot de complications :
- Frais généraux du coordinateur et du réseau: Le nœud coordinateur doit interroger plusieurs nœuds, ce qui peut allonger les temps de réponse.
- Impact sur les grandes partitions : Les lectures en lots de grande taille peuvent entraîner des problèmes de performance, en particulier pour les grandes partitions.
- Localité et distribution des données : La mise en lots peut perturber la localité des données, un facteur clé de la performance de Cassandra, et entraîner des opérations plus lentes.
- Risque de points chauds : Une distribution inégale des lectures par lots peut créer des points chauds, ce qui affecte l'équilibrage de la charge dans le cluster.
Pour atténuer ces problèmes, il peut être plus avantageux de travailler avec des opérations de lecture ciblées qui s'alignent sur les points forts de Cassandra en matière de traitement des données distribuées.
Au cours de notre voyage chez DoorDash, nous avons appris que la mise en lots dans Cassandra ne suit pas la sagesse conventionnelle des systèmes RDBMS traditionnels. Qu'il s'agisse de lectures ou d'écritures, chaque opération de mise en lots doit être soigneusement évaluée dans le contexte de la nature distribuée de Cassandra et des caractéristiques de traitement des données. En procédant ainsi, nous avons réussi à optimiser notre utilisation de Cassandra, en atteignant un équilibre entre les performances, la fiabilité et l'efficacité des ressources.
Le DataCenter ne sert pas à isoler les requêtes
Cassandra utilise des centres de données (DC) pour prendre en charge la disponibilité multirégionale, une fonctionnalité essentielle pour garantir la haute disponibilité et la reprise après sinistre. Cependant, il existe une idée fausse concernant l'utilisation des centres de données dans Cassandra, en particulier chez les personnes en transition depuis les systèmes SGBDR traditionnels. Il peut sembler intuitif de traiter un DC comme une réplique en lecture, de la même manière que les répliques en lecture sont utilisées dans les SGBDR pour l'équilibrage de la charge et le déchargement des requêtes. Mais dans Cassandra, cette approche doit être soigneusement étudiée.
Chaque DC dans Cassandra peut participer à la réplication des données ; cette réplication est vitale pour la résilience globale du système. Bien qu'il soit possible de désigner un DC pour les charges de travail lourdes en lecture - comme nous l'avons fait chez DoorDash avec notre DC en lecture seule - cette décision n'est pas sans contrepartie.
Un aspect essentiel à comprendre est le concept de contre-pression. Dans notre configuration, le DC en lecture seule n'est utilisé que pour les opérations de lecture. Cependant, cela n'isole pas complètement le DC principal de la charge. Lorsque le DC en lecture seule subit une charge élevée ou d'autres problèmes, il peut créer une contre-pression qui a un impact sur le DC principal. En effet, dans un cluster Cassandra, tous les DC sont interconnectés et participent à la santé globale du cluster et au processus de réplication des données.
Par exemple, si le DC en lecture seule est submergé par des requêtes lourdes ou de mauvaise qualité, il peut ralentir, ce qui entraîne une augmentation des temps de latence. Ces retards peuvent se répercuter sur le DC principal, qui attend des accusés de réception ou tente de gérer la cohérence de la réplication entre les DC. De tels scénarios peuvent entraîner une réduction du débit et une augmentation des temps de latence à l'échelle du cluster, et pas seulement au sein du DC en lecture seule.
Dans l'un de nos clusters Cassandra, nous avons utilisé son DC en lecture seule pour héberger des requêtes analytiques coûteuses qui prennent un instantané quotidien des tables. Comme nous considérions le DC en lecture seule comme compliqué et isolé, les requêtes devenaient de plus en plus coûteuses au fur et à mesure que le nombre de tables augmentait. Finalement, le travail d'analyse a fait en sorte que le DC RO soit bloqué à 100 % tous les soirs. Cela a également commencé à avoir un impact sur le DC principal. En collaboration avec l'équipe produit, nous avons considérablement optimisé ces travaux par lots et créé une meilleure façon de prendre l'instantané. Sans entrer dans les détails, nous avons utilisé toke range pour parcourir l'anneau de manière aléatoire et répartir la charge sur les clusters. La figure 4 ci-dessous montre l'architecture approximative.
Le résultat final a été stupéfiant. Le pic de CPU a été éliminé, ce qui nous a permis de déclasser complètement le DC RO. Les performances du DC principal en ont également bénéficié.
GC tuning : Cela en vaut parfois la peine
Dans Cassandra, l'optimisation du GC (garbage collection tuning) est une tâche difficile. Il nécessite une compréhension approfondie des mécanismes de collecte des déchets au sein de la machine virtuelle Java (JVM), ainsi que de la manière dont Cassandra interagit avec ces systèmes. Malgré sa complexité, le réglage fin du processus de ramassage des ordures peut apporter des améliorations significatives en termes de performances, en particulier dans les environnements à haut débit comme le nôtre chez DoorDash. Voici quelques considérations courantes :
- Préférer des collectes plus fréquentes de la jeune génération: Dans la collecte des déchets de la JVM, les objets sont d'abord alloués dans la jeune génération, qui est généralement plus petite et collectée plus fréquemment. Configurer Cassandra pour favoriser des collectes de jeunes générations plus fréquentes peut aider à effacer rapidement les objets à courte durée de vie, réduisant ainsi l'empreinte mémoire globale. Cette approche implique souvent d'ajuster la taille de la jeune génération et la fréquence des collectes afin de trouver un équilibre entre la récupération rapide de la mémoire et le fait de ne pas surcharger le système avec trop de pauses GC.
- Éviter les collections de l'ancienne génération : Les objets qui survivent à plusieurs collections de la jeune génération sont promus à l'ancienne génération, qui est collectée moins fréquemment. Les collections de l'ancienne génération sont plus gourmandes en ressources et peuvent entraîner des temps de pause plus longs. Dans une base de données comme Cassandra, où la constance des performances est essentielle, il est crucial de minimiser les collections de l'ancienne génération. Cela peut impliquer non seulement de régler la taille des générations jeunes et anciennes, mais aussi d'optimiser l'utilisation de la mémoire et les structures de données de Cassandra afin de réduire la quantité de déchets produits.
- Ajuster l'algorithme du ramasse-miettes : Les différents garbage collectors ont des caractéristiques différentes et sont adaptés à différents types de charges de travail. Par exemple, le garbage collector G1 est souvent un bon choix pour Cassandra, car il peut gérer efficacement de grands tas avec des temps de pause minimes. Cependant, le choix et le réglage du ramasse-miettes doivent être basés sur des modèles de charge de travail spécifiques et sur le comportement observé dans votre environnement.
- Contrôler et ajuster en fonction des mesures : Pour être efficace, le réglage du CG doit faire l'objet d'une surveillance et d'ajustements continus. Les principales mesures à surveiller sont les temps de pause, la fréquence des collectes et le taux d'allocation et de promotion des objets. Des outils tels que JMX, les outils de surveillance de la JVM et les mesures propres à Cassandra peuvent fournir des informations précieuses sur le comportement du GC et son impact sur les performances globales.
- Comprendre l'impact sur le débit et la latence : Tout réglage du GC doit tenir compte de son impact sur le débit et la latence. Alors qu'un GC plus agressif peut réduire l'empreinte mémoire, il peut également introduire des pauses plus fréquentes, ce qui affecte la latence. L'objectif est de trouver une configuration qui offre un équilibre optimal pour votre charge de travail spécifique.
Notre expérience chez DoorDash nous a permis de constater qu'un réglage ciblé du GC, bien que complexe, peut être très bénéfique. En analysant soigneusement nos charges de travail et en ajustant de manière itérative nos paramètres GC, nous avons réussi à réduire les temps de pause et à augmenter le débit et la fiabilité du système dans son ensemble. Toutefois, il convient de noter que le réglage du CG n'est pas une tâche ponctuelle, mais un processus continu d'observation, d'ajustement et d'optimisation. La figure 6 ci-dessous donne un exemple du moment où nous avons ajusté notre GC pour obtenir de meilleures performances sur P99.
Travaux futurs et applications
Alors que nous nous tournons vers l'avenir chez DoorDash, notre voyage avec Apache Cassandra va s'approfondir et évoluer. L'un de nos objectifs permanents est d'affiner l'optimisation des requêtes. Nous nous penchons sur les nuances de la taille des lots et nous évitons les anti-modèles qui nuisent à l'efficacité.
Un autre défi à relever est celui de la performance de la capture des données de changement, ou CDC. Notre configuration actuelle avec Debezium, associé à Cassandra 3, souffre de limitations en termes de latence, de fiabilité et d'évolutivité. Nous envisageons une transition vers Cassandra 4 et les clients bruts, qui offrent de meilleures capacités de CDC. Ce changement n'est pas seulement une mise à niveau technique, c'est un mouvement stratégique pour ouvrir de nouveaux domaines de traitement et d'intégration de données en temps réel.
L'observabilité dans Cassandra est une autre frontière que nous sommes impatients de conquérir. Le paysage actuel rend difficile le discernement des subtilités de la performance des requêtes. Pour mettre en lumière ces aspects cachés, nous nous lançons dans une initiative visant à intégrer notre propre couche de proxy. Cet ajout, tout en introduisant un saut supplémentaire dans notre flux de données, promet une multitude d'informations sur la dynamique des requêtes. Il s'agit d'un compromis calculé, dont nous pensons qu'il enrichira notre compréhension et notre contrôle de nos opérations de données.
Remerciements
Cette initiative ne serait pas un succès sans l'aide de nos partenaires, les DRI des différents clusters qui ont été accordés, y compris :
- Équipe d'annonceurs : Chao Chu, Deepak Shivaram, Michael Kniffen, Erik Zhang et Taige Zhang
- Équipe de commande : Cesare Celozzi, Maggie Fang et Abhishek Sharma
- Équipe du public : Edwin Zhang
- Équipe Menu & Données : Yibing Shi, Jonathan Brito, Xilu Wang et Santosh Vanga
Merci également à Levon Stepanian pour son aide dans le suivi des économies réalisées sur les frais de gestion d'AWS Infra et d'Instaclustr. Enfin, merci pour le soutien de l'équipe de stockage au sens large et de nos partenaires Instaclustr.