La traduction de l'article a été préparée spécialement pour les étudiants du cours . Vous êtes intéressé à vous développer dans ce domaine ? Nous vous invitons à notre , où nous expliciterons le programme, les particularités du format en ligne, les compétences et les perspectives de carrière qui attendent les diplômés après leur formation.

PostgreSQL et les paramètres de cohérence d'écriture pour chaque connexion spécifique
Chez Compose, nous travaillons avec de nombreuses bases de données, ce qui nous permet de mieux connaître leurs fonctionnalités et leurs inconvénients. Au fur et à mesure que nous apprenons à apprécier les caractéristiques fonctionnelles des nouvelles bases de données, nous commençons parfois à nous demander ce que ce serait bien si de telles fonctionnalités étaient également présentes dans des outils plus matures avec lesquels nous travaillons depuis longtemps. Une des nouvelles fonctionnalités que nous aurions aimé voir dans PostgreSQL était une cohérence de l'enregistrement paramétrable par connexion dans tout le cluster. Et il s'avère que c'est déjà le cas, et aujourd'hui, nous souhaitons partager avec vous des informations sur la façon dont vous pouvez l'utiliser.
Pourquoi est-ce important ?
Le comportement du cluster dépend de votre application. Prenons par exemple une application de paiement de factures. Vous aurez besoin d'une cohérence à 100 % dans le cluster, donc vous devrez activer les engagements synchrones pour que votre base de données attende que toutes les modifications soient effectuées. Toutefois, si votre application est un réseau social en pleine expansion, vous préférerez certainement un temps de réponse rapide à la cohérence à 100 %. Pour y parvenir, vous pouvez utiliser des engagements asynchrones dans votre cluster.
Voici le compromis
Vous devrez faire un compromis entre la cohérence des données et la performance. PostgreSQL tend vers la cohérence, car la configuration par défaut dans ce cas est prévisible et sans surprises inattendues. Maintenant, découvrons ces compromis.
Compromis 1 : Performance
Si le cluster PostgreSQL ne nécessite pas de cohérence, il peut fonctionner de manière asynchrone. L'écriture se fait sur le leader du cluster, et ses répliques recevront les mises à jour après quelques millisecondes. Lorsque le cluster PostgreSQL exige la cohérence, il doit fonctionner de manière synchrone. L'écriture sera effectuée dans le leader du cluster, qui enverra la mise à jour aux répliques et attendra la confirmation que chacune d'elles a enregistré ces données, avant d'envoyer une confirmation au client qui a initié l'écriture, informant que celle-ci a été effectuée avec succès. La différence pratique entre ces approches réside dans le fait que la méthode asynchrone nécessite deux sauts réseau, tandis que la synchronisation en nécessite quatre.
Compromis 2 : Cohérence
Le résultat en cas de défaillance du leader dans ces deux approches sera également différent. Si le traitement s'effectue de manière asynchrone, lors d'une telle erreur, toutes les écritures ne seront pas enregistrées par les répliques. Combien seront perdues ? Cela dépend de l'application elle-même et de l'efficacité de la réplication. La réplication Compose empêchera une réplique de devenir leader si la quantité d'informations qu'elle contient est inférieure de 1 Mo à celle du leader, ce qui signifie qu'il pourrait potentiellement y avoir jusqu'à 1 Mo d'écritures perdues en cas de fonctionnement asynchrone.
En mode synchrone, cela ne se produit pas. Si le leader échoue, toutes les répliques se mettent à jour, puisque toute écriture validée sur le leader doit également être confirmée dans les répliques. Voilà ce qu'est la cohérence.
Le comportement synchrone a du sens à utiliser dans une application de paiement de factures, où la cohérence a un avantage évident dans la recherche d'un compromis entre cohérence et performance. La chose la plus importante pour une telle application est des données valides. Pensez maintenant à un réseau social, où l'objectif principal est de capter l'attention de l'utilisateur en répondant aux demandes le plus rapidement possible. Dans ce cas, la performance, avec moins de sauts réseaux et moins d'attente pour les commits, sera prioritaire. Cependant, le compromis entre performance et cohérence n'est pas le seul auquel il faut penser.
Compromis 3 : Pannes
Il est très important de comprendre comment un cluster se comporte en cas de défaillance. Considérons la situation où une ou plusieurs répliques échouent. Lorsque les validations sont traitées de manière asynchrone, le leader continuera à fonctionner, c'est-à-dire à accepter et à traiter des enregistrements sans attendre les répliques manquantes. Lorsque les répliques reviennent dans le cluster, elles rattrapent le leader. Avec la réplication synchronisée, si les répliques ne répondent pas, le leader n'aura d'autre choix que de continuer à attendre la confirmation de la validation jusqu'à ce que la réplique revienne dans le cluster et puisse accepter et confirmer l'enregistrement.
Une connexion par transaction ?
Chaque application a besoin d'un type particulier de combinaison entre cohérence et performance. À moins qu'il ne s'agisse de notre application de paiement de factures, que nous considérons comme entièrement cohérente, ou de notre application de réseau social presque éphémère. Dans tous les autres cas, il y aura des moments où certaines opérations doivent être synchrones et d'autres asynchrones. Vous ne voudrez peut-être pas que le système attende que le message envoyé dans le chat soit validé, mais si un paiement se déroule dans la même application, il faudra attendre.
Toutes ces décisions, bien sûr, sont prises par le développeur de l'application. Les bonnes décisions quant à quand appliquer telle ou telle approche aideront à tirer le meilleur parti du cluster. Il est important que le développeur puisse passer d'une méthode à l'autre au niveau SQL pour les connexions et pour les transactions.
Assurer le contrôle en pratique
Par défaut, PostgreSQL garantit la cohérence. Cela est contrôlé par le paramètre du serveur synchronous_commit. Par défaut, il est en position on, mais il a trois autres options : local, remote_write ou off.
En réglant le paramètre sur off tous les commits synchrones sont arrêtés, même dans le système local. Le paramètre local détermine le mode synchrone pour le système local, mais les enregistrements dans les répliques sont effectués de manière asynchrone. Remote_write va encore plus loin : les enregistrements dans les répliques sont effectués de manière asynchrone, mais sont renvoyés lorsque la réplique a accepté l'enregistrement, mais ne l'a pas écrit sur le disque.
En considérant la gamme d'options disponibles, nous choisissons le comportement et, en gardant à l'esprit que on sont des enregistrements synchrones, nous choisirons local pour les commits asynchrones sur le réseau, tout en gardant les commits locaux synchrones.
Nous allons maintenant vous expliquer comment configurer cela en un rien de temps, mais imaginez que nous avons installé synchronous_commit dans local pour le serveur. Nous nous sommes demandé s'il était possible de modifier le paramètre synchronous_commit à la volée, et il s'avère que ce n'est pas seulement possible, il existe même deux façons de le faire. La première consiste à définir la session de votre connexion de la manière suivante:
SET SESSION synchronous_commit TO ON;
// Vos écritures vont iciTous les enregistrements ultérieurs dans la session confirmeront les opérations d'écriture pour les réplicas avant de renvoyer un résultat positif au client connecté. Bien sûr, à moins que vous ne changiez à nouveau le paramètre synchronous_commit . Vous pouvez omettre la partie SESSION dans la commande, car elle prendra la valeur par défaut.
La deuxième méthode est utile lorsque vous souhaitez simplement vous assurer que vous obtenez la réplication synchronisée pour une seule transaction. Dans de nombreuses bases de données de la génération «NoSQL», le concept de transactions n'existe pas, mais il existe dans PostgreSQL. Dans ce cas, vous lancez une transaction, puis vous définissez synchronous_commit dans on avant d'exécuter l'écriture pour la transaction. COMMIT enregistrera la transaction en utilisant n'importe quelle valeur du paramètre synchronous_commit, qui a été définie à ce moment-là, bien qu'il soit préférable de définir la variable à l'avance afin de s'assurer que d'autres développeurs comprennent que les enregistrements ne sont pas asynchrones.
BEGIN;
SET LOCAL synchronous_commit TO ON;
// Vos écritures vont ici
COMMIT; Tous les engagements de transactions seront désormais confirmés, comme s'ils étaient écrits dans les réplicas avant même que la base de données ne renvoie une réponse positive au client connecté.
Configuration de PostgreSQL
Auparavant, nous avions en tête un système PostgreSQL avec synchronous_commit, installé sur local. Pour que cela soit réel du côté serveur, vous devrez définir deux paramètres de configuration du serveur. Un autre paramètre synchronous_standby_names entrera en vigueur lorsque synchronous_commit sera dans on. Il définit quelles réplicas sont autorisées à effectuer des engagements synchrones, et nous allons le configurer à *, ce qui signifiera impliquer tous les réplicas. Ces valeurs sont généralement configurées dans en ajoutant :
synchronous_commit = local
synchronous_standby_names='*'En définissant le paramètre synchronous_commit à la valeur local, nous créons un système dans lequel les disques locaux restent synchrones, mais les engagements des réplicas réseau sont par défaut asynchrones. À moins, bien sûr, que nous ne décidions de rendre ces engagements synchrones, comme montré ci-dessus.
Si vous avez suivi l'évolution , vous avez peut-être remarqué quelques changements récents (, ), qui ont permis aux utilisateurs de Governor de tester ces paramètres et de contrôler leur cohérence.
Encore quelques mots…
Il y a tout juste une semaine, je vous aurais dit qu'il était impossible de régler PostgreSQL aussi finement. C'est alors que Kurt, membre de l'équipe de la plateforme Compose, a insisté sur le fait qu'une telle possibilité existait. Il a apaisé mes objections et a trouvé dans la documentation de PostgreSQL :

Ce paramètre peut être modifié à tout moment. Le comportement de toute transaction est déterminé par le réglage en vigueur lors du commit. Il est donc possible et utile que pour certaines transactions, les commits soient effectués de manière synchrone, tandis que pour d'autres, cela se fasse de manière asynchrone. Par exemple, pour forcer un multistatement transaction à effectuer des commits de manière asynchrone, lorsque la valeur du paramètre par défaut est opposée, définissez SET LOCAL synchronous_commit TO OFF dans la transaction.
Avec une telle petite modification dans le fichier de configuration, nous avons donné aux utilisateurs la possibilité de contrôler leur cohérence et leur performance.
Source : habr.com
