Revenir au contenu principal
Ingénierie

Comment l'architecture lakehouse accélère les écritures Postgres par 5

Résoudre le goulot d'étranglement des performances structurelles dans Postgres géré

par David Wein et Vlad Lazar

  • Lakebase offre désormais un débit jusqu'à 5 fois supérieur pour les charges de travail OLTP intensives en écriture, un problème courant pour les applications Postgres à grande échelle.
  • L'architecture lakebase nous permet de décharger les tâches critiques de récupération après incident de la couche de calcul vers le stockage distribué.
  • Des échantillons de production montrent des améliorations de débit d'écriture de 4,5x sur 32 vCPU et une réduction de 94 % du trafic WAL, tout en réduisant la latence de lecture de la queue de 2x sans compromettre la durabilité.

Dans une lakebase, le calcul et le stockage sont séparés par conception. Bien que cette séparation ait été initialement conçue pour la flexibilité opérationnelle, y compris la mise à l'échelle, le branchement et la récupération instantanée, elle ouvre également un énorme potentiel de performance.

En dissociant ces couches, nous pouvons décharger le travail de votre calcul Postgres vers notre stockage distribué d'une manière structurellement impossible dans les déploiements Postgres monolithiques traditionnels. Dans cet article, nous allons explorer comment nous avons exploité cet avantage architectural pour éliminer un goulot d'étranglement Postgres vieux de dix ans afin d'améliorer le débit d'écriture Postgres de 5x, tout en réduisant les latences de lecture de fin de 2x et le trafic WAL de 94%.

Le coût caché de la durabilité traditionnelle de Postgres

Pour comprendre comment nous avons obtenu une amélioration de 5x des performances de Postgres géré, nous devons examiner comment Postgres gère la durabilité.

Dans Postgres, chaque modification de base de données est d'abord enregistrée dans un journal séquentiel (le Write-Ahead Log, ou WAL) pour garantir que les données ne sont pas perdues en cas de crash. Pour accélérer les temps de récupération après un crash, Postgres effectue périodiquement un événement de nettoyage en arrière-plan appelé "checkpoint". Contrairement à un instantané, un checkpoint est simplement un marqueur de jalon dans le journal. Pendant un checkpoint, Postgres prend toutes les données modifiées actuellement en mémoire (gérées par blocs de 8 Ko appelés "pages") et les écrit sur le disque principal, jusqu'à un point spécifique du journal. En cas de crash, Postgres restaure vos données en partant de ce jalon de checkpoint et en rejouant les journaux WAL récents sur le disque.

Cependant, il y a un risque : si le serveur plante exactement au moment où il enregistre une page de 8 Ko sur le disque, la page peut être partiellement écrite, ce qui entraîne une "page déchirée" corrompue. Si Postgres essaie de rejouer une petite mise à jour du journal sur une page déchirée, les données sont définitivement ruinées. Pour résoudre ce problème, Postgres doit s'assurer qu'il ne s'appuie jamais sur un disque corrompu pour la récupération.

Il le fait en utilisant un "Full Page Write" (FPW). La toute première fois qu'une page est modifiée après un jalon de checkpoint, Postgres n'enregistre pas seulement la petite modification ; il copie la page entière de 8 Ko dans le WAL. En cas de crash et si la page disque est déchirée, Postgres ignore le disque ruiné, récupère la sauvegarde vierge de 8 Ko du WAL et l'utilise comme point de départ idéal pour rejouer le reste des journaux. Bien que cela garantisse une sécurité absolue, c'est coûteux : sur les applications à forte charge d'écriture, l'enregistrement de pages entières de 8 Ko peut multiplier le volume du journal jusqu'à 15 fois, devenant souvent le principal goulot d'étranglement des performances du système.

La solution lakebase : éliminer le risque de pages déchirées

Dans l'architecture lakebase, votre calcul est sans état. Il ne dépend pas d'un répertoire de données local. Au lieu de cela, il diffuse le WAL vers un quorum de gardiens basé sur Paxos.

Comme il n'y a pas de page sur disque local à déchirer, le mode de défaillance que le FPW a été conçu pour prévenir n'existe tout simplement pas. Cependant, désactiver naïvement le FPW crée un problème secondaire : les performances de lecture. Sans ces images de page complètes périodiques dans le journal, la couche de stockage devrait rejouer une chaîne infinie de petits deltas pour reconstruire une page pour une requête de lecture. Ce qui était autrefois un replay borné O(fréquence de checkpoint) devient une chaîne illimitée, entraînant un pic de latence de lecture et de consommation de ressources.

Innovation : génération d'images poussée vers le stockage distribué

Nous avons résolu ce problème en déplaçant l'intelligence du nœud de calcul vers la couche de stockage. Nous appelons cela la génération d'images poussée.

Lorsque le calcul Postgres demande une page au stockage, le pageserver (un composant du système de stockage distribué Lakebase) la reconstruit en trouvant l'image matérialisée la plus récente de cette page et en rejouant les deltas WAL par-dessus. Les images de page complètes que le calcul utilisait pour intégrer dans le WAL servaient de points de réinitialisation périodiques dans cette chaîne de deltas, maintenant naturellement la chaîne raisonnablement bornée et les lectures rapides. Pour un traitement plus approfondi de ce mécanisme, voir Plongée dans le moteur de stockage Neon.

Avec les écritures de page complètes désactivées, ces points de réinitialisation disparaissent. Sans intelligence supplémentaire dans le système de stockage distribué, une page fréquemment mise à jour pourrait accumuler une longue chaîne de petits deltas sans image intermédiaire. Le résultat serait une augmentation indésirable de la latence de lecture et de la consommation de ressources, car le pageserver rejouerait toute la chaîne pour servir une lecture, augmentant la latence et la consommation de ressources.

Pour éviter ce problème, nous avons poussé la responsabilité de génération d'images du flux WAL du calcul vers la couche de stockage, préservant le comportement de lecture borné du stockage tout en éliminant la surcharge WAL sur le calcul. Le pageserver génère maintenant des images de page complètes lorsqu'une page a accumulé plus d'enregistrements delta qu'un seuil configuré sans image intermédiaire. C'est une approche naturellement meilleure car la décision de générer une nouvelle image est basée sur le nombre réel de modifications d'une page plutôt que sur le processus de checkpoint Postgres non lié.

Voici pourquoi c'est nettement mieux pour les performances :

  1. Efficacité réseau: Le calcul n'envoie que les deltas compacts, qui sont les modifications réelles, entraînant une réduction de 94% du trafic dans nos benchmarks.
  2. Scalabilité: Le travail est déplacé de l'unique écrivain Postgres vers la couche de stockage distribuée et indépendamment évolutive. La génération d'images pour une branche de projet est maintenant partagée entre plusieurs pageservers en arrière-plan.
  3. Lectures optimales: La génération des images est maintenant basée sur les modifications réelles d'une page plutôt que sur le processus de checkpoint Postgres non lié.

Quantification de l'impact : du laboratoire à la production

Nous avons benchmarké cette optimisation en utilisant HammerDB TPROC-C (un benchmark OLTP dérivé de TPC-C) et validé les résultats sur des charges de travail de production réelles.

1. Mise à l'échelle du calcul sans serveur

Le débit est mesuré en nouvelles commandes par minute (NOPM). Les gains augmentent considérablement avec la taille de l'instance de calcul :

Taille du calcul

Avant (NOPM)

Après (NOPM)

Gain de débit

4 cœurs virtuels

78 876

94 891

20%

16 cœurs virtuels

95 832

269 189

2,8x

32 cœurs virtuels

95 686

439 300

4,5x+

Sur un calcul de 32 cœurs virtuels, l'amélioration a dépassé 450%.

Avec les images de page complètes générées sur le calcul, chaque transaction génère en moyenne 58 Ko de WAL. Avec la génération d'images poussée, cela tombe à moins de 4 Ko, soit une réduction de 94%. L'amélioration du débit en découle directement : moins de WAL signifie moins de contention sur le chemin d'écriture, moins de bande passante réseau consommée et moins de travail pour la couche de stockage à ingérer.

En supprimant le goulot d'étranglement FPW de Postgres, nous avons permis au débit de s'adapter linéairement aux ressources de calcul. C'est quelque chose que Postgres monolithique a du mal à faire sous une forte charge d'écriture.

2. Validation en production dans le monde réel

Dans un environnement de production pour un projet de 56 cœurs virtuels de premier plan, l'activation de la génération d'images poussée a réduit la génération de WAL en régime permanent de 30 Mo/s à seulement 1 Mo/s.

Taux de WAL client en production : (plus bas c'est mieux)

Cette diminution du volume s'est directement corrélée à une augmentation du débit de transactions pendant les pics quotidiens.

Cela n'a pas seulement aidé les écritures. En optimisant les chaînes delta, le nombre d'enregistrements WAL qui doivent être appliqués par lecture a considérablement diminué. Nous avons constaté une baisse des latences de lecture p99 de 30 % à 50 % et une baisse des latences p50 d'environ 30 %.

Débit client en production : (plus c'est élevé, mieux c'est)


En élargissant la perspective, au niveau régional, après l'activation, nous avons constaté que la quantité totale de WAL générée par les calculs a été réduite jusqu'à 4 fois. La latence p99 des lectures à partir du moteur de stockage s'est améliorée jusqu'à 3 fois et est devenue beaucoup plus stable.

Taux d'ingestion de WAL régional (plus c'est bas, mieux c'est)
Latence de récupération de page p99 de stockage régional (plus c'est bas, mieux c'est)

3. Tables synchronisées Lakebase

Pour les tables synchronisées gourmandes en données, l'impact a été immédiat. Un client a vu son débit d'ingestion passer de 17k lignes par seconde à 62k lignes par seconde, soit une augmentation de 3x, simplement en activant le transfert d'images.

Déploiement transparent : performances sans interruption

Depuis fin mars, nous avons déployé cela sur l'ensemble de notre flotte. C'est maintenant actif pour toutes les bases de données Lakebase Serverless et Neon dans le monde.

La modification a été appliquée aux calculs en cours d'exécution via notre plan de contrôle et notre système de stockage, qui ont coordonné la transition automatiquement. Cela a été réalisé en utilisant le mécanisme existant d'enregistrement WAL de Postgres XLOG_FPW_CHANGE WAL, ce qui signifie qu'aucun redémarrage ou interruption n'a été requis pour nos clients.

Quelle est la prochaine étape pour les performances de Postgres géré ?

L'architecture lakebase a été conçue pour la flexibilité, mais elle a été conçue pour la performance. Le transfert des écritures de page complètes fait partie d'un effort systématique pour récolter les bénéfices de la séparation du stockage et du calcul.

Tout comme nous avons introduit le préchauffage du cache pour le patching sans temps d'arrêt, nous continuons à déplacer les tâches lourdes de vos transactions vers notre pile de stockage d'arrière-plan évolutive. La taxe d'écriture Postgres est officiellement une chose du passé.

(Cet article de blog a été traduit à l'aide d'outils basés sur l'intelligence artificielle) Article original

Recevez les derniers articles dans votre boîte mail

Abonnez-vous à notre blog et recevez les derniers articles directement dans votre boîte mail.