Slony-I™ effectue une grande partie de sa maintenance lui-même, dans un processus de « nettoyage » qui :
supprime les anciennes données sur les différentes tables du schéma de Slony-I™, notamment sl_log_1, sl_log_2 et sl_seqlog ;
effectue un VACUUM sur certaines tables utilisées par Slony-I™. À partir de la version 1.0.5, ceci inclut pg_listener ; dans les versions antérieures, vous devez lancer souvent des VACUUM sur cette table, sinon vous verrez votre réplication ralentir car Slony-I™ lève beaucoup d'événements, qui mènent à ce que la table contienne de nombreuses lignes mortes.
Avec certaines versions (la 1.1, peut-être la 1.0.5), il est possible de ne plus s'embarrasser avec les VACUUM sur ces tables si vous utilisez quelque chose comme pg_autovacuum pour gérer le nettoyage de ces tables. Malheureusement, il est possible que pg_autovacuum ne nettoie pas assez fréquemment, vous pourrez donc préférer utiliser les VACUUM internes. Nettoyer la table pg_listener « trop souvent » est moins risqué que de ne pas la nettoyer assez.
Malheureusement, si vous avez de longues transactions, les VACUUM ne peuvent pas nettoyer les lignes mortes qui sont plus récentes que les anciennes transactions toujours en cours. Ceci conduira en particulier à une forte croissance de pg_listener et ralentira la réplication.
Le bogue violation par clef dupliquée a permis d'isoler un certain nombre de cas d'exceptions assez obscures au niveau de PostgreSQL™. Donc, dans les versions modernes de Slony-I™ et PostgreSQL™, il n'y a pas lieu de s'inquiéter.
À partir de la version 1.2, la fonctionnalité « log switching » est arrivée ;de temps en temps (par défaut une fois par semaine bien que vous pouvez modifier cela en appelant la procédure stockée logswitch_start()), elle tente d'interchanger les données entre sl_log_1 et sl_log_2 afin de réaliser un TRUNCATE sur les « plus vieilles » données.
Cela signifie que, de manière régulière, ces tables sont complètement nettoyées ce qui évite qu'elles ne grossissent trop lors d'une charge importante et qu'elles deviennent impossibles à nettoyer.
En version 2.0, DELETE n'est plus utilisé pour nettoyer les données dans sl_log_1 et sl_log_2 ; à la place, la logique de la bascule des logs est utilisée fréquemment, à chaque fois que la boucle de nettoyage ne trouve pas une bascule en cours. Cela permet de nettoyer proprement ces tables via TRUNCATE. Ceci élimine le besoin d'un VACUUM pour ces tables.
Les versions récentes dePostgreSQL™ proposent un processus « autovacuum » qui détecte les modifications sur les tables et la création de lignes mortes, puis nettoie ces tables, « à la demande ». On a constaté que cela peut interagir de manière négative avec la politique de VACUUM de Slony-I™ sur ces propres tables.
Slony-I™ demande des VACUUM sur ses tables immédiatement après avoir complété les transactions qui sont sensées supprimer de vieilles données, ce qui est considéré comme le meilleur moment pour le faire. Il semble que l'autovacuum détecte les changements un peu trop tôt, et lance un VACUUM alors que les transactions ne sont pas terminées, ce qui est relativement inutile. Il apparaît préférable de configurer l'autovacuum pour éviter les tables de configuration gérées par Slony-I™.
La requête suivante identifie les tables que l'autovacuum ne doit pas traiter (remplacez le nom du cluster par celui de votre configuration locale) :
moncluster=# select oid, relname from pg_class where relnamespace = (select oid from pg_namespace where nspname = '_' || 'monCluster') and relhasindex; oid | relname -------+-------------- 17946 | sl_nodelock 17963 | sl_setsync 17994 | sl_trigger 17980 | sl_table 18003 | sl_sequence 17937 | sl_node 18034 | sl_listen 18017 | sl_path 18048 | sl_subscribe 17951 | sl_set 18062 | sl_event 18069 | sl_confirm 18074 | sl_seqlog 18078 | sl_log_1 18085 | sl_log_2 (15 rows)
La requête suivante remplira la table pg_catalog.pg_autovacuum avec les informations de configuration adéquates : INSERT INTO pg_catalog.pg_autovacuum (vacrelid, enabled) SELECT oid, 'f' FROM pg_catalog.pg_class WHERE relnamespace = (SELECT oid FROM pg_namespace WHERE nspname = '_' || 'monCluster') AND relhasindex;
Il y a deux scripts « chiens de garde » disponibles pour surveiller la réplication et relancer les processus slon lorsqu'ils meurent pour telle ou telle raison, par exemple une « coupure » réseau qui provoque une perte de connectivité.
Ils pourraient vous être utiles...
La « meilleure et nouvelle » façon de gérer les processus slon(1) se fait via une combinaison de Section 21.2, « mkslonconf.sh », qui crée un fichier de configuration pour chaque nœud d'un cluster, et Section 21.4, « launch_clusters.sh » qui utilise ces fichiers de configuration.
Cette approche est préférable aux anciens systèmes de « chiens de garde » car vous pouvez « pointer » précisément, dans chaque fichier de configurationn, le paramètrage désiré pour chaque nœud, sans avoir à vous préoccuper des options que le script chien de garde vous propose (ou pas). Ceci est particulièrement important si vous utilisez le log shipping, auquel cas oublier l'option -a peut ruiner le nœud destinataire du log shipping et ruiner par là-même votre journée.
Un nouveau script est apparu dans Slony-I™ 1.1, il s'agit de generate_syncs.sh, qui est utilise dans les situations suivantes.
Supposons que vous avez un serveur non fiable sur lequel le démon slon ne fonctionne pas en continu, en rentrant de week-end vous vous trouverez peut-être la situation suivante :
Le vendredi soir, quelque chose s'est « cassé » et le temps que la base de donnée redémarre, aucun des démons slon n'a survécu. Votre application en ligne a ensuite connu trois jours de charge transactionnelle relativement forte.
Lorsque vous redémarrez slon le lundi, il n'y a pas eu de synchronisation sur le maître depuis vendredi, ce qui fait que le prochain « ensemble de SYNC » comprendra toutes les modifications entre vendredi et lundi. Aïe !
Si vous lancez generate_syncs.sh via une tache cron toute les 20 minutes, cela créera de force des événements SYNC sur l'origine, ce qui implique qu'entre vendredi et lundi, les nombreuses mises à jour seront découpées en plus de 100 ensembles de SYNC, qui pourront être appliqués de manière incrémentale, rendant la restauration moins déplaisante.
Notez que si les SYNC sont exécutés régulièrement, ce scripts ne fera rien de particulier.
Dans le répertoire tools, vous trouverez les scripts Section 5.1, « test_slony_state » nommés test_slony_state.pl et test_slony_state-dbi.pl. Le premier utilise l'interface Perl/DBI, l'autre utilise l'interface PostgreSQL.
Les deux font essentiellement la même chose, c'est-à-dire se connecter à un nœud Slony-I™ (celui de votre choix) et, à partir de là, détermine la liste des nœuds du cluster. Ensuite ils lancent une série de requêtes (en lecture seule, donc sans danger) afin de parcourir différentes tables à la recherche de différentes conditions susceptibles de revéler des problèmes, telles que :
Gonflement des tables comme pg_listener, sl_log_1, sl_log_2, sl_seqlog ;
Voies d'écoute ;
Analyse de la propagation des événements ;
Analyse de la propagation des confirmations.
Si la communication est légèrement perturbée, la réplication peut fonctionner, mais les confirmations peuvent ne pas être retournées, ce qui empêche les nœuds de nettoyer les vieux événements et les anciennes données de réplication.
Lancer ce script une fois par heure ou une fois par jour peut vous aider à détecter les symptomes précurseurs de certains problèmes, avant même que cela conduise à une dégradation des performances.
Dans le répertoire tools, on peut trouver quatre scripts qui peuvent être utilisés pour surveiller des instances Slony-I™ :
test_slony_replication est un script Perl auquel vous pouvez passer les informations de connexion d'un nœud Slony-I™. Il teste alors la table sl_path et d'autres informations sur ce nœud afin de déterminer la forme de l'ensemble de réplication choisi.
Ensuite il injecte des requêtes de test dans la table nommée slony_test qui est définie comme ci-dessous, et qui doit être ajoutée à l'ensemble des tables répliquées :
CREATE TABLE slony_test (
description text,
mod_date timestamp with time zone,
"_Slony-I_testcluster_rowID" bigint DEFAULT nextval('"_testcluster".sl_rowid_seq'::text) NOT NULL
);
La dernière colonne de la table est définie par Slony-I™ comme une clé primaire manquante...
Ce script génère une ligne de sortie pour chaque nœud Slony-I™ actif pour l'ensemble de réplication défini dans un fichier nommé cluster.fact.log.
Il y a une option additionelle, finalquery, qui vous permet de passer une requête SQL spécifique à votre application pour déterminer l'état de votre application.
log.pm est un module Perl module qui gère les logs des scripts Perl.
run_rep_tests.sh est un script « wrapper » qui lance test_slony_replication.
Si vous avez plusieurs clusters Slony-I™, vous pouvez placer dans ce fichier la configuration pour se connecter à tous ces clusters.
nagios_slony_test est un script qui a été construit pour interroger les fichiers logs afin de pouvoir lancer le test de réplication régulièrement (nous le laissons toutes les six minutes) et qu'un outil de supervision tel que Nagios™ puisse utiliser le script pour surveiller l'état indiqué dans ces logs.
Il semble plus efficace qu'une tache cron lance les tests et que Nagios™ vérifie le résultat plutôt que de voir Nagios™ lancer directement les tests. Ces tests peuvent vérifier l'ensemble du cluster Slony-I™ d'un seul coup, plutot que de voir Nagios™ provoquer des mises à jour en permanence.
La méthodologie de la section précédente est conçu avec un vue pour minimiser le coût des requêtes de tests ; sur un cluster très chargé, supportant des centaines d'utilisateurs, le coût associé aux quelques requêtes de test n'est pas un point important et le temps de configuration des tables et des injecteurs de données est très élevé.
Trois autres méthodes sont apparus pour analyser l'état de la réplication :
Pour un test orienté sur l'application, il est utile de créer une vue sur une table fréquemment mise à jour pour remonter des informations spécifiques à l'application.
Par exemple, on peut chercher soit des statistiques sur les objets applicatifs les plus récents, soit les transactions de l'application. Par exemple :
CREATE VIEW replication_test AS SELECT now() - txn_time AS age, object_name FROM transaction_table ORDER BY txn_time DESC LIMIT 1;
CREATE VIEW replication_test AS SELECT now() - created_on AS age, object_name FROM object_table ORDER BY id DESC LIMIT 1;
Il y a un inconvénient : cette approche nécessite que vous ayez une activité constante sur le système impliquant la création de nouvelles transactions de manière régulière. Si quelque chose ne fonctionne pas dans votre application, vous obtiendrez des fausses alertes en provenance de la réplication alors même que la réplication fonctionne correctement.
La vue Slony-I™ nommée sl_status fournit des informations sur la synchronisation des différents nœuds. Son contenu n'est intéressant que sur les nœuds origine car les événements générés sur les autres nœuds peuvent généralement être ignorés.
Voir également la discussion sur Section 5.3, « Surveiller Slony-I avec MRTG ».
Les démons slon(1) génère des journaux applicatifs plus ou moins verbeux, selon le niveau de débogage activé. Dans ce cas, vous pouvez :
Utiliser un programme de rotation des journaux applicatifs comme rotatelogs d'Apache™ pour avoir une séquence de journaux applicatifs et éviter d'avoir des journaux trop gros ;
Purgez régulièrement les vieux journaux applicatifs.
Ce script crée un répertoire pour le service slon qui pourra être utilisé avec la commande svscan de daemontools. Ce script utilise multilog de manière très basique, ce qui semble être standard pour les installations daemontools / multilog. Si vous souhaitez une gestion intelligente des journaux applicatifs, consultez la section logrep ci-dessous. Actuellement, ce script a des possibilités de gestion d'erreurs très limitées.
Pour les usages non-interactifs, configurez les variables d'environnement suivantes : BASEDIR, SYSUSR, PASSFILE, DBUSER, HOST, PORT, DATABASE, CLUSTER et SLON_BINARY. Si une seule de ces valeurs n'est pas définie, le script demande les informations de manière interactive.
BASEDIR, l'emplacement où la structure du répertoire du service slon sera créée. Il ne faut pas que ce soit le répertoire /var/service ;
SYSUSR, l'utilisateur unix qui lancera le processus slon (et multilog) ;
PASSFILE, l'emplacement du fichier .pgpass (par défaut ~sysusr/.pgpass) ;
DBUSER, l'utilisateur postgres que slon doit utiliser (par défaut slony) ;
HOST, l'adresse du serveur ou slon doit se connecter (par défaut localhost) ;
PORT, le port de connexion (par défaut 5432) ;
DATABASE, la base de données sur laquelle slon se connecte (par défaut dbuser)
CLUSTER, le nom du cluster Slony1 (par défaut database) ;
SLON_BINARY, le chemin complet vers le binaire slon (par défaut which slon).
Ce script utilise tail -F pour extraire des données des journaux applicatifs en vous permettant d'utiliser des filtres multilog (via l'option CRITERIA) afin de créer des journaux de transactions spécifiques. Le but est de fournir un moyen de surveiller les journaux de transactions en temps réel en quête de données « intéressante » sans devoir modifier le journal applicatif initial ou gacher des ressources CPU/IO en parcourant les journaux régulièrement.
Pour une utilisation non interactive, il faut configurer les variables : BASEDIR, SYSUSR, SOURCE, EXTENSION et CRITERIA. Si une seule de ces options n'est pas définie, le script demande interactivement les informations de configuration.
BASEDIR, l'emplacement où sera créée la structure du répertoire du service de logrep. Il ne faut pas que ce soit le répertoire /var/service.
SYSUSR, l'utilisateur unix qui lancera le service.
SOURCE, le nom du service de log que vous voulez utiliser.
EXTENSION, une balise pour différencier ce logrep de ceux qui utilisent la même source.
CRITERIA, le filtre multilog que vous voulez utiliser.
Un exemple trivial consiste à produire un journal applicatif de tous les messages d'erreur slon qui pourraient être utilisés pour déclencher une alerte nagios : EXTENSION='ERRORS' CRITERIA="'-*' '+* * ERROR*'" (on relance la surveillance en déclenchant une rotation des journaux applicatifs avec svc -a $svc_dir)
Une application plus intéressante est la surveillance de la progression d'une souscription d'un nœud : EXTENSION='COPY' CRITERIA="'-*' '+* * ERROR*' '+* * WARN*' '+* * CONFIG enableSubscription*' '+* * DEBUG2 remoteWorkerThread_* prepare to copy table*' '+* * DEBUG2 remoteWorkerThread_* all tables for set * found on subscriber*' '+* * DEBUG2 remoteWorkerThread_* copy*' '+* * DEBUG2 remoteWorkerThread_* Begin COPY of table*' '+* * DEBUG2 remoteWorkerThread_* * bytes copied for table*' '+* * DEBUG2 remoteWorkerThread_* * seconds to*' '+* * DEBUG2 remoteWorkerThread_* set last_value of sequence*' '+* * DEBUG2 remoteWorkerThread_* copy_set*'"
Si vous avez une trace d'abonnement, alors il est facile de déterminer si un nœud donné est en train de réaliser une copie ou une autre activité de souscription. Si les journaux applicatifs ne sont pas vide et ne se terminent pas par "CONFIG enableSubscription: sub_set:1" (où 1 est le numéro d'ensemble de réplication que vous avez abonné) alors le slon est au milieu d'une copie initiale.
Si vous surveillez l'horodatage de modification du journal applicatif de votre nœud primaire pour déterminer si le slon est tombé dans le coma, vérifier cette trace d'abonnement est un bon moyen d'éviter de stopper le nœud alors qu'un abonnement est en cours. En bonus, puisque les slons utilisent svscan, vous pouvez simplement détruire le fichier (via l'interface svc) et laisser svscan le recommencer plus tard. J'ai également découvert que les traces de COPY sont pratiques pour suivre de manière interactive l'activité des abonnements.