PostgreSQL et les paramètres de cohérence des enregistrements pour chaque connexion particulière

La traduction de l'article a été préparée spécialement pour les étudiants du cours "Base de données" . Est-il intéressant de se développer dans cette direction? Nous vous invitons à Open Doors Day , où nous parlerons en détail du programme, des caractéristiques du format en ligne, des compétences et des perspectives de carrière qui attendent les diplômés après la formation.



PostgreSQL et les paramètres de cohérence des enregistrements pour chaque connexion particulière
Chez Compose, nous devons gérer de nombreuses bases de données, ce qui nous donne l'occasion d'en savoir plus sur leurs fonctionnalités et leurs inconvénients. Alors que nous apprenons à aimer les caractéristiques fonctionnelles des nouvelles bases de données, nous commençons parfois à penser à quel point il serait bon que des fonctions similaires soient présentes dans des outils plus matures avec lesquels nous travaillons depuis longtemps. L'une des nouvelles fonctionnalités que PostgreSQL voulait voir était sa cohérence d'écriture personnalisée sur l'ensemble du cluster. Et comme il s'est avéré, nous l'avons déjà, et aujourd'hui nous voulons partager avec vous des informations sur la façon dont vous pouvez l'utiliser.


Pourquoi ai-je besoin de ça?


Le comportement d'un cluster dépend de votre application. Prenons, par exemple, une demande de paiement de factures. Vous aurez besoin d'une cohérence à 100% dans le cluster, vous devrez donc activer les validations synchrones pour que votre base de données attende que toutes les modifications soient apportées. Cependant, si votre application est un réseau social à croissance rapide, vous préférerez probablement une cohérence à 100% avec une réponse rapide. Pour ce faire, vous pouvez utiliser des validations asynchrones dans votre cluster.


Rencontrez le compromis


Vous devez faire un compromis entre la cohérence des données et les performances. PostgreSQL s'éloigne de la cohérence, car la configuration par défaut dans ce cas est prévisible et sans surprise inattendue. Et maintenant, nous allons nous familiariser avec les compromis.


Compromis 1: Performance


Si le cluster PostgreSQL ne nécessite pas de cohérence, il peut très bien fonctionner de manière asynchrone. L'enregistrement est fait pour le chef de cluster, et les mises à jour seront envoyées à ses répliques après quelques millisecondes. Lorsque la cohérence est requise pour un cluster PostgreSQL, il doit fonctionner de manière synchrone. L'enregistrement sera effectué dans le leader du cluster, qui enverra des mises à jour aux répliques et attendra la confirmation que tout le monde a créé un enregistrement avant d'envoyer une confirmation au client qui a initié l'enregistrement de sa réussite. La différence pratique entre ces approches est que la méthode asynchrone nécessite deux sauts de réseau, tandis que la méthode synchrone en requiert quatre.


Compromis 2: cohérence


Le résultat en cas de dysfonctionnement d'un leader dans ces deux approches sera également différent. Si le travail est effectué de manière asynchrone, lorsqu'une telle erreur se produit, tous les enregistrements ne seront pas validés par des répliques. Combien sera perdu? Dépend de l'application elle-même et de l'efficacité de la réplication. La réplication Compose empêchera le réplica de devenir un leader si la quantité d'informations qu'il contient est inférieure de 1 Mo à celle du leader, c'est-à-dire que jusqu'à 1 Mo d'enregistrements peuvent potentiellement être perdus pendant le fonctionnement asynchrone.


En mode synchrone, cela ne se produit pas. Si le leader échoue, toutes les répliques sont mises à jour, car tout enregistrement confirmé sur le leader doit être confirmé dans les répliques. Le voici - la cohérence.


Il est logique d'utiliser un comportement synchrone dans une application pour payer des factures, où la cohérence présente un avantage évident dans la recherche d'un compromis entre cohérence et performances. La chose la plus importante pour une telle application est des données valides. Rappelez-vous maintenant du réseau social, dans lequel la tâche principale est de garder l'attention de l'utilisateur, en répondant aux demandes le plus rapidement possible. Dans ce cas, les performances avec moins de sauts de réseau et moins de validations d'attente seront une priorité. Cependant, le compromis entre performance et cohérence n'est pas le seul à penser.


Compromis 3: échecs


Il est très important de comprendre le comportement du cluster lors d'une panne. Considérez une situation où une ou plusieurs répliques échouent. Lorsque les validations sont traitées de manière asynchrone, le leader continuera de fonctionner, c'est-à-dire de recevoir et de traiter les enregistrements sans attendre les réplicas manquants. Lorsque les répliques reviennent au cluster, elles rattrapent le leader. Avec la réplication synchrone, si les répliques ne répondent pas, le leader n'aura pas le choix et il continuera d'attendre la confirmation de la validation jusqu'à ce que la réplique revienne au cluster et puisse accepter et confirmer l'enregistrement.


Une connexion par transaction?


Chaque application a besoin d'un type spécial de combinaison de cohérence et de performances. À moins bien sûr que ce soit notre application de facturation, qui nous semble tout à fait cohérente, ou notre application de réseau social quasi é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é au chat soit validé, mais si le paiement est effectué dans la même application, vous devrez attendre.


Bien entendu, toutes ces décisions sont prises par le développeur de l'application. Les bonnes décisions quant au moment d'appliquer telle ou telle approche aideront à tirer le meilleur parti du cluster. Il est important que le développeur puisse basculer entre eux au niveau SQL pour les connexions et pour les transactions.


Assurer le contrôle dans la pratique


Par défaut, PostgreSQL assure la cohérence. Ceci est contrôlé par le paramètre du serveur synchronous_commit . Par défaut, il est remote_write , mais il a trois autres options: local , remote_write ou off .


Lorsque le paramètre est défini sur off , toutes les validations synchrones sont arrêtées, même dans le système local. Le paramètre en local détermine le mode synchrone pour le système local, mais les écritures sur les répliques sont asynchrones. Remote_write va encore plus loin: les écritures sur les répliques sont effectuées de manière asynchrone, mais sont renvoyées lorsque la réplique a reçu l'enregistrement mais ne l'a pas écrit sur le disque.


Compte tenu de la gamme d'options disponibles, nous choisissons le comportement et, en nous souvenant que les enregistrements sont synchrones, nous choisirons local pour les validations asynchrones sur le réseau, tout en laissant les validations locales synchrones.


Maintenant, nous allons vous dire comment configurer cela en un instant, mais imaginez que nous définissons synchronous_commit sur local pour le serveur. Nous nous sommes demandé s'il était possible de changer le paramètre synchronous_commit à la volée, et il s'est avéré que ce n'est pas seulement possible, il y a même deux façons de le faire. La première consiste à configurer votre session de connexion comme suit:


 SET SESSION synchronous_commit TO ON; // Your writes go here 

Tous les enregistrements suivants de la session confirmeront les opérations d'écriture pour les répliques avant de renvoyer un résultat positif au client connecté. Sauf si, bien sûr, vous modifiez à nouveau le paramètre synchronous_commit . Vous pouvez omettre la partie SESSION de la commande car elle aura la valeur par défaut.


La deuxième méthode est bonne lorsque vous voulez simplement vous assurer d'obtenir une réplication synchrone pour une seule transaction. Dans de nombreuses bases de données NoSQL, le concept de transactions n'existe pas, mais il existe dans PostgreSQL. Dans ce cas, vous démarrez la transaction, puis définissez synchronous_commit sur on avant d'écrire dans la transaction. COMMIT la transaction en utilisant n'importe quelle valeur du paramètre synchronous_commit qui a été définie à ce moment, bien qu'il soit préférable de définir la variable à l'avance pour vous assurer que les autres développeurs comprennent que les enregistrements ne sont pas asynchrones.


 BEGIN; SET LOCAL synchronous_commit TO ON; // Your writes go here COMMIT; 

Toutes les validations de transaction seront désormais confirmées comme écrites dans les répliques avant que la base de données ne renvoie une réponse positive au client connecté.


Configuration de PostgreSQL


Avant cela, nous avons imaginé un système PostgreSQL avec synchronous_commit défini sur local . Pour que cela soit réel côté serveur, vous devrez définir deux paramètres de configuration du serveur. Un autre paramètre synchronous_standby_names prendra le relais lorsque synchronous_commit est synchronous_commit . Il détermine quelles répliques sont éligibles pour les validations synchrones, et nous allons le définir sur * , ce qui signifie que toutes les répliques sont activées. Ces valeurs sont généralement configurées dans le fichier de configuration en ajoutant:


 synchronous_commit = local synchronous_standby_names='*' 

En définissant le paramètre synchronous_commit sur local , nous créons un système dans lequel les lecteurs locaux restent synchrones, mais les validations de réplique réseau sont asynchrones par défaut. À moins, bien sûr, que nous décidions de rendre ces validations synchrones, comme indiqué ci-dessus.


Si vous avez suivi le développement du projet Governor , vous avez peut-être remarqué des changements récents ( 1 , 2 ), 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 à peine une semaine, je vous dirais qu'il n'est pas possible d'affiner PostgreSQL si finement. C'est alors que Kurt, membre de l'équipe de la plateforme Compose, a insisté sur le fait qu'il y avait une telle opportunité. Il a apaisé mes objections et a trouvé ce qui suit dans la documentation PostgreSQL:



Ce paramètre peut être modifié à tout moment. Le comportement de toute transaction est déterminé par le paramètre en vigueur lors de la validation. Par conséquent, il est possible et utile que les validations soient validées de manière synchrone pour certaines transactions et de manière asynchrone pour d'autres. Par exemple, pour forcer une transaction multistatement unique à se valider de manière asynchrone lorsque la valeur par défaut du paramètre est l'inverse, définissez SET LOCAL synchronous_commit TO OFF dans la transaction.


Avec cette petite modification dans le fichier de configuration, nous avons donné aux utilisateurs la possibilité de contrôler leur cohérence et leurs performances.

Source: https://habr.com/ru/post/fr472364/


All Articles