PostgreSQL
 sql >> Base de données >  >> RDS >> PostgreSQL

Un guide de PGpool - Conseils et observations :troisième partie

Dans la partie précédente, j'ai osé jouer avec une fonctionnalité non implémentée en fantasmant sur son fonctionnement. Eh bien, la haute disponibilité est avant tout une question de conception et ensuite seulement de mise en œuvre. Cela n'excuse pas une mauvaise mise en œuvre, ni ne rend la conception naïve intelligente. Pourtant, après avoir couvert tous les scénarios possibles et trouvé une meilleure règle adéquate pour la plupart des cas, parfois un petit changement très primitif peut ruiner la forteresse. Ci-dessous, je veux sandbox.

Que se passe-t-il lorsque pgpool doit basculer, mais ne peut pas ?

Lorsque la vérification de l'état du maître échoue, la commande failover_command est déclenchée pour dégénérer tout ou promouvoir l'esclave suivant en primaire. Sonne solide. Que se passe-t-il s'il échoue lui-même, par exemple la connexion ssh échoue (par exemple, parce que other - bad admin remove key from ~/.ssh/authorized_keys). Qu'avons-nous ?

Dès que health_check_timeout (20 par défaut) est dépassé (également affecté par le délai de nouvelle tentative, le nombre maximum de retraits, etc.), le nœud devient mort, donc :

t=# select nid,port,st from dblink('host=localhost port=5433','show pool_nodes') as t (nid int,hostname text,port int,st text,lb_weight float,role text,cnt int,cur_node text,del int);
 nid | port |  st
-----+------+------
   0 | 5400 | down
   1 | 5401 | up
   2 | 5402 | up
(3 rows)

Il ne reste donc plus aucune nouvelle tentative et le basculement a échoué. La première option consiste évidemment à effectuer le basculement manuellement. Mais si le basculement échoue à cause d'une erreur stupide, le maître est de retour sur les rails, et le seul problème que vous avez est que pgpool pense que le maître est hors ligne - vous voudriez probablement laisser les choses telles qu'elles étaient avant l'accident à la place - n'est-ce pas ? Bien sûr, il ne suffit pas de remettre le maître en ligne. Pgpool a déjà "dégénéré" le primaire. Le simple fait de l'ajouter en tant que nouveau nœud n'aidera pas non plus. Le pire est qu'après l'événement, pgpool n'essaiera pas de vérifier si l'ancien maître est pg_is_in_recovery() ou non, et ne l'acceptera donc jamais comme principal. Selon la piste de bogue, vous devez "Supprimer le fichier pgpool_status et ne pas restaurer l'état précédent" avec la commande pgpool -D.

Après avoir ignoré le statut, nous nous reconnectons pour éviter de voir le serveur fermer la connexion de manière inattendue et exécuter :

t=# select nid,port,st,role from dblink('host=localhost port=5433','show pool_nodes') as t (nid int,hostname text,port int,st text,lb_weight float,role text,cnt int,cur_node text,del int);
 nid | port | st |  role
-----+------+----+---------
   0 | 5400 | up | primary
   1 | 5401 | up | standby
   2 | 5402 | up | standby
(3 rows)

Tous les nœuds sont de retour et fonctionnent, pgpool reconnaît le maître.

Enfin, je veux couvrir quelques conseils et observations sur l'utilisation de pgpool :

  • La modification des paramètres du backend est un peu délicate :le nom d'hôte, le port et le répertoire nécessitent un rechargement pour ajouter de nouveaux nœuds, mais nécessitent un redémarrage pour modifier l'existant. Alors que le poids et le drapeau peuvent être modifiés en rechargeant simplement.

  • Ne confondez pas les valeurs de la colonne load_balance_node avec la configuration. Si vous ne voyez qu'un seul nœud avec true, ce n'est pas seulement OK - c'est ainsi. Cela ne signifie pas que vous n'avez qu'un seul nœud dans le pool d'équilibrage - cela montre simplement quel nœud est choisi pour cette session particulière. Ci-dessous, le résultat de la requête avec les trois nœuds participant à l'équilibrage des instructions SELECT, avec l'ID de nœud 2 choisi :

    t=# show pool_nodes;
     node_id | hostname  | port | status | lb_weight |  role   | select_cnt | load_balance_node | replication_delay
    ---------+-----------+------+--------+-----------+---------+------------+-------------------+-------------------
     0       | localhost | 5400 | up     | 0.125000  | primary | 61         | false             | 0
     1       | localhost | 5401 | up     | 0.312500  | standby | 8          | false             | 0
     2       | localhost | 5402 | up     | 0.562500  | standby | 11         | true              | 0
    (3 rows)
  • Vous pouvez vérifier quel nœud a été choisi pour l'équilibrage de charge avec show pool_nodes, mais vous vous souciez de le connaître pour votre requête, pas celle de "show", donc une telle vérification n'est pas toujours suffisamment informative. Eh bien, vous pouvez surveiller quel nœud vous utilisez pour la requête en cours, avec quelque chose comme :

    t=# select *,current_setting('port') from now();
                  now              | current_setting
    -------------------------------+-----------------
     2018-04-09 13:56:17.501779+01 | 5401
    (1 row)

Important! Mais non :

t=# select now, setting from now() join pg_settings on name='port';
             now             | setting
-----------------------------+---------
 2018-04-09 13:57:17.5229+01 | 5400
(1 row)

Comme il retournera TOUJOURS le port du maître. Il en va de même pour tout pg_catalog SELECT.

  • Comme vous l'avez remarqué dans les parties précédentes, j'utilise une méthode plus compliquée que de simplement afficher pool_nodes pour répertorier les nœuds avec l'état. Je le fais délibérément pour montrer comment vous pouvez rendre le résultat gérable. L'utilisation de where rend la requête plus longue, mais le résultat clair, en sautant tout ce qui détourne l'attention de notre tâche particulière. Comparez :

t=# select nid,port,st,role from dblink('host=localhost port=5433','show pool_nodes') as t (nid int,hostname text,port int,st text,lb_weight float,role text,cnt int,cur_node text,del int);
 nid | port | st |  role
-----+------+----+---------
   0 | 5400 | up | primary
   1 | 5401 | up | standby
   2 | 5402 | up | standby

Avec la sortie du show pool_nodes initial...

  • Vous ne pouvez pas comparer pgbouncer et pgpool. Mais si vous le faites, le plus important est de savoir que l'analyse des requêtes dans pgpool dépend de la version de pg. Ainsi, lors de la mise à niveau de postgreSQL, vous devez également mettre à niveau pgpool, tandis qu'une instance de pgbouncer peut avoir une configuration pour 8,9,10 clusters différents dans le même fichier ini.

  • Pourquoi ne puis-je pas utiliser uniquement un script de basculement au lieu de pgpool ? Tu peux. Mais pgpool l'offre AVEC le memcached et la mise en commun des connexions et l'équilibrage et le contrôle du cerveau partagé et est vérifié par des décennies d'utilisation.

  • Le système de suivi des bogues est en place - cela vaut la peine de le visiter si vous travaillez avec pgpool :https://www.pgpool.net/mantisbt/my_view_page.php

  • De nombreuses fautes de frappe dans la documentation, comme bakance (backend + balance? ..), statemnet, allowed ou mismatch à travers la version (pool_nodes était autrefois int et sont maintenant enum, mais le lien vers les anciennes valeurs dans pcp_node-info est toujours là) gâte l'impression sur ce merveilleux produit. Un formulaire pour envoyer le rapport sur les "bogues" trouvés dans la documentation (tout comme "soumettre une correction" sur les docs postgres) l'améliorerait grandement.

  • Conseil important : avant de vous fier à une étape - vérifiez-la. Par exemple. après avoir promu le nœud, vous ne pouvez pas le reproduire (ici, la promotion n'est pas une opération postgres, mais plutôt l'enregistrement du nœud en tant que maître pour pgpool) :

    [email protected]:~# sudo -u postgres pcp_promote_node -w -h 127.0.0.1 -U vao -n 1
    pcp_promote_node -- Command Successful
    [email protected]:~# sudo -u postgres pcp_promote_node -w -h 127.0.0.1 -U vao -n 1
    FATAL:  invalid pgpool mode for process recovery request
    DETAIL:  specified node is already primary node, can't promote node id 1

Cela semble logique et a fière allure. Pourtant, si vous l'exécutez sur le mauvais nœud (par exemple, le nœud 0 est ! pg_is_in_recovery) :

[email protected]:~# for i in $(seq 1 3); do pcp_promote_node -w -h 127.0.0.1 -U vao -n 0; echo $?; done
pcp_promote_node -- Command Successful
0
pcp_promote_node -- Command Successful
0
pcp_promote_node -- Command Successful
0

Ce qui est mauvais car vous ne pouvez pas reproduire le nœud et vous attendre à une erreur, mais vous obtenez le statut de sortie 0…

Téléchargez le livre blanc aujourd'hui PostgreSQL Management &Automation with ClusterControlDécouvrez ce que vous devez savoir pour déployer, surveiller, gérer et faire évoluer PostgreSQLTélécharger le livre blanc

Conseil important :ne jouez pas trop. Ne jouez jamais en prod !

En jouant avec recovery_1st_stage_command en utilisant pg_rewind, j'ai pensé essayer par curiosité un autre hack de singe - en interrogeant pgpool_recovery() sans arguments (car je les ignore de toute façon dans ma configuration) puis en essayant simplement d'attacher le nœud à pgpool :

[email protected]:~# psql -p 5433 -h localhost template1 -c "SELECT pgpool_recovery('or_1st.sh', '', '', '')"
 pgpool_recovery
-----------------
 t
(1 row)

[email protected]:~# pcp_attach_node -h 127.0.0.1 -U vao -w -n 1
pcp_attach_node -- Command Successful

Cette idée stupide m'a amené à :

[email protected]:~# ps -aef | grep pgpool
postgres 15227     1  0 11:22 ?        00:00:00 pgpool -D
postgres 15240 15227  0 11:22 ?        00:00:00 pgpool: health check process(0)
postgres 15241 15227  0 11:22 ?        00:00:00 pgpool: health check process(1)
postgres 15242 15227  0 11:22 ?        00:00:00 pgpool: health check process(2)
postgres 15648 15227  0 11:24 ?        00:00:00 [pgpool] <defunct>
postgres 16264 15227  0 11:26 ?        00:00:00 pgpool: PCP: wait for connection request
postgres 16266 15227  0 11:26 ?        00:00:00 [pgpool] <defunct>
postgres 16506 16264  0 11:26 ?        00:00:00 pgpool: PCP: processing recovery request
postgres 16560 15227  0 11:26 ?        00:00:00 [pgpool] <defunct>
postgres 16835 15227  0 11:26 ?        00:00:00 [pgpool] <defunct>
postgres 16836 15227  0 11:26 ?        00:00:00 [pgpool] <defunct>

Pas d'échappatoire, je dois :

[email protected]:~# kill -9 
[email protected]:~# rm /var/run/pgpoolql/.s.PGSQL.5433
[email protected]:~# rm /var/run/pgpoolql/.s.PGSQL.9898

Au-dessus de 5433 se trouve le port pgpool et 9898 est le port pcp. Évidemment après un crash, les fichiers ne sont pas balayés, vous devez donc le faire manuellement.

  • Lisez attentivement et jouez beaucoup avant de mettre pgpool en production. Il est beaucoup plus difficile de trouver de l'aide avec pgpool que postgres lui-même. Certaines questions ne trouvent jamais de réponse. Surtout quand on m'a posé la question au mauvais endroit (j'ai répondu en me basant sur le bon endroit pour obtenir la réponse)...
  • N'oubliez pas la dernière chronologie pour la réplication en cascade (pas vraiment l'indice pgpool, mais souvent les gens ne comprennent pas que pour récupérer un nouveau maître, il ne suffit pas de spécifier un bon point de terminaison pour le récepteur).
  • L'architecture avec diagramme peut être trouvée ici.

Conclusion

En 10 ans, de nouvelles fonctionnalités prometteuses (watchdog et virtual ip) et des correctifs importants (par exemple serialize_accept) sont apparus, mais dans l'ensemble, cela laisse une impression sous-évaluée. Les docs ont des fautes de frappe qui y vivent depuis 10 ans. Je ne crois pas que personne ne lise les docs. Je ne crois pas que personne ne l'ait remarqué. Vous ne pouvez tout simplement pas les signaler de manière simple. Il y a beaucoup d'armes chargées et préparées, allongées sur le site de documentation pour que l'utilisateur novice puisse les prendre, les pointer contre le pied et appuyer sur la gâchette. Je n'ai aucune idée raisonnable de comment l'améliorer - je préviens juste les tireurs. Une mauvaise interprétation d'un paramètre peut vous plonger dans une position désespérée d'ingénierie inverse pour trouver votre erreur. Pendant toutes ces années, pgpool a été et reste une sorte de produit pour les utilisateurs avancés. En lisant la documentation, je n'ai pas pu m'empêcher de ne pas me souvenir de la vieille blague russe sur Sherlock Holmes :Sherlock et Watson volent sur le ballon. Soudain, le vent fort les emporte à des milliers de kilomètres. Lorsqu'ils peuvent atterrir, ils voient la fille paître des moutons. Holmes demande à la fille :« Chéri, où sommes-nous ? et la fille répond "Tu es sur le ballon!". Sherlock remercie et alors qu'ils décollent dit "Le vent nous a emmené très loin - nous sommes en Russie". "Mais comment savez-vous?" demande Watson. "C'est évident - il n'y a qu'en Russie que les codeurs font paître les moutons", répond Sherlock. "Mais comment savez-vous que la fille est codeuse?" - "C'est évident - elle nous a donné une réponse absolument précise et totalement inutile".