Hvad er replikeringspladser?
Dengang hvor "replikeringsslots" endnu ikke blev introduceret, var det en udfordring at administrere WAL-segmenterne. I standard streaming-replikering har masteren intet kendskab til slavestatus. Tag eksemplet med en master, der udfører en stor transaktion, mens en standby node er i vedligeholdelsestilstand i et par timer (såsom opgradering af systempakkerne, justering af netværkssikkerhed, hardwareopgradering osv.). På et tidspunkt fjerner masteren sin transaktionslog (WAL-segmenter), når kontrolpunktet passerer. Når først slaven er ude af vedligeholdelse, har den muligvis et enormt slavelag og skal indhente masteren. Til sidst vil slaven få et fatalt problem som nedenfor:
LOG: started streaming WAL from primary at 0/73000000 on timeline 1
FATAL: could not receive data from WAL stream: ERROR: requested WAL segment 000000010000000000000073 has already been removed
Den typiske fremgangsmåde er at specificere i din postgresql.conf et WAL-arkiveringsscript, der vil kopiere WAL-filer til en eller flere langsigtede arkivsteder. Hvis du ikke har nogen standbys eller andre streaming-replikeringsklienter, kan serveren grundlæggende kassere WAL-filen, når arkivscriptet er færdigt eller svarer OK. Men du skal stadig bruge nogle nyere WAL-filer til gendannelse af nedbrud (data fra seneste WAL-filer afspilles igen under gendannelse af nedbrud. I vores eksempel på en standby-node, som er placeret i en lang vedligeholdelsesperiode, opstår der problemer, når den kommer online igen og spørger den primære for en WAL-fil, som den primære ikke længere har, så mislykkes replikeringen.
Dette problem blev løst i PostgreSQL 9.4 via "Replication Slots".
Hvis du ikke bruger replikeringspladser, er en almindelig måde at reducere risikoen for mislykket replikering ved at indstille wal_keep_segments højt nok, så de WAL-filer, der måtte være nødvendige, ikke bliver roteret eller genbrugt. Ulempen ved denne tilgang er, at det er svært at afgøre, hvilken værdi der er bedst for din opsætning. Du behøver ikke vedligeholdelse på daglig basis, eller du behøver ikke at beholde en stor bunke WAL-filer, der æder dit disklager. Selvom dette virker, er det ikke en ideel løsning, da risiko for diskplads på masteren kan forårsage, at indgående transaktioner mislykkes.
Alternative metoder til ikke at bruge replikeringspladser er at konfigurere PostgreSQL med kontinuerlig arkivering og give en restore_command for at give replikaen adgang til arkivet. For at undgå opbygning af WAL på den primære, kan du bruge en separat volumen eller lagerenhed til WAL-filerne, f.eks. SAN eller NFS. En anden ting er med synkron replikering, da det kræver, at den primære skal vente på standby-noder for at begå transaktion. Det betyder, at det sikrer, at WAL-filer er blevet anvendt på standby-knuderne. Men alligevel er det bedst, at du giver arkiveringskommandoer fra den primære, så når først WAL'er er genbrugt i den primære, kan du være sikker på, at du har WAL-sikkerhedskopier i tilfælde af gendannelse. Selvom synkron replikering i nogle situationer ikke er en ideel løsning, da den kommer med nogle præstationsomkostninger sammenlignet med asynkron replikering.
Typer af replikeringspladser
Der er to typer replikeringspladser. Disse er:
Fysiske replikeringspladser
Kan bruges til standard streaming replikering. De vil sørge for, at data ikke genbruges for tidligt.
Logiske replikeringspladser
Logisk replikering gør det samme som fysiske replikeringspladser og bruges til logisk replikering. De bruges dog til logisk afkodning. Ideen bag logisk afkodning er at give brugerne en chance for at knytte sig til transaktionsloggen og afkode den med et plugin. Det giver mulighed for at udtrække ændringer foretaget til databasen og derfor til transaktionsloggen i ethvert format og til ethvert formål.
I denne blog vil vi bruge fysiske replikeringsslots, og hvordan man opnår dette ved hjælp af ClusterControl.
Fordele og ulemper ved at bruge replikeringsslots
Replikeringspladser er absolut fordelagtige, når de først er aktiveret. Som standard er "replikeringspladser" ikke aktiveret og skal indstilles manuelt. Blandt fordelene ved at bruge replikeringsslots er
- Sikker på, at master beholder nok WAL-segmenter til, at alle replikaer kan modtage dem
- Forhindrer masteren i at fjerne rækker, der kan forårsage gendannelseskonflikt på replikaerne
- En master kan kun genbruge transaktionsloggen, når den er blevet brugt af alle replikaer. Fordelen her er, at en slave aldrig kan komme så meget bagud, at en re-sync er nødvendig.
Replikeringspladser kommer også med nogle forbehold.
- En forældreløs replikeringsplads kan forårsage ubegrænset diskvækst på grund af ophobede WAL-filer fra masteren
- Slaveknuder, der er placeret under lang vedligeholdelse (såsom dage eller uger), og som er bundet til en replikeringsplads, vil have ubegrænset diskvækst på grund af ophobede WAL-filer fra masteren
Du kan overvåge dette ved at forespørge pg_replication_slots for at bestemme de pladser, der ikke bruges. Vi vender tilbage til dette lidt senere.
Brug af replikeringspladser
Som tidligere nævnt er der to typer replikeringspladser. Til denne blog bruger vi fysiske replikeringspladser til streamingreplikering.
Oprettelse af en replikeringsplads
Oprettelse af en replikering er enkel. Du skal aktivere den eksisterende funktion pg_create_physical_replication_slot for at gøre dette og skal køres og oprettes i masterknuden. Funktionen er enkel,
maximus_db=# \df pg_create_physical_replication_slot
Schema | pg_catalog
Name | pg_create_physical_replication_slot
Result data type | record
Argument data types | slot_name name, immediately_reserve boolean DEFAULT false, OUT slot_name name, OUT xlog_position pg_lsn
Type | normal
f.eks. Oprettelse af en replikeringsplads ved navn slot1,
postgres=# SELECT pg_create_physical_replication_slot('slot1');
-[ RECORD 1 ]-----------------------+---------
pg_create_physical_replication_slot | (slot1,)
Replikeringspladsnavnene og dens underliggende konfiguration er kun systemdækkende og ikke klyngedækkende. For eksempel, hvis du har nodeA (nuværende master) og standby noder nodeB og nodeC, der skaber slot på en master nodeA, nemlig "slot1", så vil data ikke være tilgængelige for nodeB og nodeC. Derfor, når failover/switchover er ved at ske, skal du genskabe de slots, du har oprettet.
Sletning af en replikeringsplads
Ubrugte replikationspladser skal slettes eller slettes. Som nævnt tidligere, når der er forældreløse replikationsslots eller slots, der ikke er blevet tildelt til nogen klient- eller standby-knudepunkter, kan det føre til ubegrænsede diskpladsproblemer, hvis de ikke er fjernet. Så det er meget vigtigt, at disse skal droppes, når de ikke længere er i brug. For at slippe det, skal du blot påkalde pg_drop_replication_slot. Denne funktion har følgende definition:
maximus_db=# \df pg_drop_replication_slot
Schema | pg_catalog
Name | pg_drop_replication_slot
Result data type | void
Argument data types | name
Type | normal
Det er nemt at droppe det:
maximus_db=# select pg_drop_replication_slot('slot2');
-[ RECORD 1 ]------------+-
pg_drop_replication_slot |
Overvågning af dine PostgreSQL-replikeringspladser
Overvågning af dine replikeringspladser er noget, du ikke vil gå glip af. Indsaml blot oplysningerne fra view pg_replication_slots i den primære/master node ligesom nedenfor:
postgres=# select * from pg_replication_slots;
-[ RECORD 1 ]-------+-----------
slot_name | main_slot
plugin |
slot_type | physical
datoid |
database |
active | t
active_pid | 16297
xmin |
catalog_xmin |
restart_lsn | 2/F4000108
confirmed_flush_lsn |
-[ RECORD 2 ]-------+-----------
slot_name | main_slot2
plugin |
slot_type | physical
datoid |
database |
active | f
active_pid |
xmin |
catalog_xmin |
restart_lsn |
confirmed_flush_lsn |
Ovenstående resultat viser, at main_slot er blevet taget, men ikke main_slot2.
En anden ting, du kan gøre, er at overvåge, hvor meget halter efter de slots, du har. For at opnå dette kan du blot bruge forespørgslen baseret på eksempelresultatet nedenfor:
postgres=# SELECT redo_lsn, slot_name,restart_lsn,
round((redo_lsn-restart_lsn) / 1024 / 1024 / 1024, 2) AS GB_behind
FROM pg_control_checkpoint(), pg_replication_slots;
redo_lsn | slot_name | restart_lsn | gb_behind
------------+-----------+-------------+-----------
1/8D400238 | slot1 | 0/9A000000 | 3.80
Men redo_lsn er ikke til stede i 9.6, skal bruge redo_location, så i 9.6,
imbd=# SELECT redo_location, slot_name,restart_lsn,
round((redo_location-restart_lsn) / 1024 / 1024 / 1024, 2) AS GB_behind
FROM pg_control_checkpoint(), pg_replication_slots;
-[ RECORD 1 ]-+-----------
redo_location | 2/F6008BE0
slot_name | main_slot
restart_lsn | 2/F6008CC0
gb_behind | 0.00
-[ RECORD 2 ]-+-----------
redo_location | 2/F6008BE0
slot_name | main_slot2
restart_lsn | 2/F6008CC0
gb_behind | 0.00
Systemvariable krav
Implementering af replikeringspladser kræver manuel indstilling. Der er variabler, som du skal huske på, som kræver ændringer og specificeres i din postgresql.conf. Se nedenfor:
- max_replication_slots – Hvis den er sat til 0, betyder det, at replikeringspladser er fuldstændig deaktiveret. Hvis du bruger PostgreSQL <10 versioner, skal denne slot angives andet end 0 (standard). Siden PostgreSQL 10 er standarden 10. Denne variabel specificerer det maksimale antal replikeringspladser. Indstilling af den til en lavere værdi end antallet af aktuelt eksisterende replikeringspladser forhindrer serveren i at starte.
- wal_level – skal mindst være replika eller højere (replika er standard). Indstilling af hot_standby eller arkiv vil kortlægges til replika. For en fysisk replikeringsplads er replika nok. For logiske replikeringspladser foretrækkes logisk.
- max_wal_senders – indstillet til 10 som standard, 0 i version 9.6, hvilket betyder, at replikering er deaktiveret. Vi foreslår, at du som minimum indstiller dette til 16, især når du kører med ClusterControl.
- hot_standby – i versioner <10 skal du indstille denne til On, som er slået fra som standard. Dette er vigtigt for standby-noder, hvilket betyder, at når du er tændt, kan du oprette forbindelse og køre forespørgsler under gendannelse eller i standbytilstand.
- primary_slot_name – denne variabel indstilles via recovery.conf på standby-noden. Dette er det slot, der skal bruges af modtageren eller standby-knuden, når der oprettes forbindelse til afsenderen (eller primær/master).
Du skal være opmærksom på, at disse variabler for det meste kræver en genstart af databasetjenesten for at genindlæse nye værdier.
Brug af replikeringspladser i et ClusterControl PostgreSQL-miljø
Lad os nu se, hvordan vi kan bruge fysiske replikeringspladser og implementere dem i en Postgres-opsætning, der administreres af ClusterControl.
Deployering af PostgreSQL-databasenoder
Lad os begynde at implementere en 3-node PostgreSQL Cluster ved hjælp af ClusterControl ved hjælp af PostgreSQL 9.6 version denne gang.
ClusterControl vil implementere noder med følgende systemvariabler defineret i overensstemmelse hermed baseret på deres standardindstillinger eller opjusterede værdier. I:
postgres=# select name, setting from pg_settings where name in ('max_replication_slots', 'wal_level', 'max_wal_senders', 'hot_standby');
name | setting
-----------------------+---------
hot_standby | on
max_replication_slots | 0
max_wal_senders | 16
wal_level | replica
(4 rows)
I versioner PostgreSQL> 9.6 er standardværdien for max_replication_slots 10, som er aktiveret som standard, men ikke i 9.6 eller lavere versioner, som er deaktiveret som standard. Du skal tildele max_replication_slots højere end 0. I dette eksempel satte jeg max_replication_slots til 5.
[email protected]:~# grep 'max_replication_slots' /etc/postgresql/9.6/main/postgresql.conf
# max_replication_slots = 0 # max number of replication slots
max_replication_slots = 5
og genstartede tjenesten,
[email protected]:~# pg_lsclusters
Ver Cluster Port Status Owner Data directory Log file
9.6 main 5432 online postgres /var/lib/postgresql/9.6/main pg_log/postgresql-%Y-%m-%d_%H%M%S.log
[email protected]:~# pg_ctlcluster 9.6 main restart
Indstilling af replikeringsslots for primære og standby noder
Der er ingen mulighed i ClusterControl for at gøre dette, så du skal oprette dine slots manuelt. I dette eksempel oprettede jeg pladserne i den primære i vært 192.168.30.100:
192.168.10.100:5432 [email protected]_db=# SELECT pg_create_physical_replication_slot('slot1'), pg_create_physical_replication_slot('slot2');
pg_create_physical_replication_slot | pg_create_physical_replication_slot
-------------------------------------+-------------------------------------
(slot1,) | (slot2,)
(1 row)
Tjekker, hvad vi lige har lavet, viser,
192.168.10.100:5432 [email protected]_db=# select * from pg_replication_slots;
slot_name | plugin | slot_type | datoid | database | active | active_pid | xmin | catalog_xmin | restart_lsn | confirmed_flush_lsn
-----------+--------+-----------+--------+----------+--------+------------+------+--------------+-------------+---------------------
slot1 | | physical | | | f | | | | |
slot2 | | physical | | | f | | | | |
(2 rows)
Nu i standby-noderne skal vi opdatere recovery.conf og tilføje variablen primary_slot_name og ændre application_name, så det er nemmere at identificere noden. Sådan ser det ud i vært 192.168.30.110 recovery.conf:
[email protected]:/var/lib/postgresql/9.6/main/pg_log# cat ../recovery.conf
standby_mode = 'on'
primary_conninfo = 'application_name=node11 host=192.168.30.100 port=5432 user=cmon_replication password=m8rLmZxyn23Lc2Rk'
recovery_target_timeline = 'latest'
primary_slot_name = 'slot1'
trigger_file = '/tmp/failover_5432.trigger'
Gør det samme i vært 192.168.30.120, men ændrede applikationsnavnet og indstillede det primære_slot_navn ='slot2'.
Kontrol af replikeringspladsens tilstand:
192.168.10.100:5432 [email protected]_db=# select * from pg_replication_slots;
slot_name | plugin | slot_type | datoid | database | active | active_pid | xmin | catalog_xmin | restart_lsn | confirmed_flush_lsn
-----------+--------+-----------+--------+----------+--------+------------+------+--------------+-------------+---------------------
slot1 | | physical | | | t | 24252 | | | 0/CF0A4218 |
slot2 | | physical | | | t | 11635 | | | 0/CF0A4218 |
(2 rows)
Hvad har du ellers brug for?
Da ClusterControl ikke understøtter replikeringspladser på nuværende tidspunkt, er der ting, du skal tage højde for. Hvad er disse? Lad os gå i detaljer.
Failover/Switchover-proces
Når en automatisk failover eller omskiftning via ClusterControl er blevet forsøgt, vil slots ikke blive bevaret fra de primære og på standby noderne. Du skal genskabe dette manuelt, kontrollere variablerne, hvis de er indstillet korrekt, og ændre recovery.conf i overensstemmelse hermed.
Genopbygning af en slave fra en mester
Når du genopbygger en slave, vil recovery.conf ikke blive bibeholdt. Dette betyder, at dine recovery.conf-indstillinger med det primære_slot_name vil blive slettet. Du skal angive dette manuelt igen og kontrollere pg_replication_slots-visningen for at afgøre, om slots er korrekt brugt eller efterladt forældreløse.
Hvis du vil genopbygge slave-/standby-knuden fra en master, skal du muligvis overveje at angive PGAPPNAME env-variablen ligesom kommandoen nedenfor:
$ export PGAPPNAME="app_repl_testnode15"; /usr/pgsql-9.6/bin/pg_basebackup -h 192.168.10.190 -U cmon_replication -D /var/lib/pgsql/9.6/data -p5434 -W -S main_slot -X s -R -P
Det er meget vigtigt at specificere -R-parameteren, så det vil genskabe recovery.conf, mens -S skal angive hvilket slotnavn, der skal bruges, når standby-knuden genopbygges.
Konklusion
Implementering af replikeringsslots i PostgreSQL er ligetil, men der er visse forbehold, som du skal huske. Når du implementerer med ClusterControl, skal du opdatere nogle indstillinger under failover eller slave-genopbygninger.