Vad är replikeringsplatser?
Förr i tiden när "replikeringsplatser" ännu inte introducerades, var det en utmaning att hantera WAL-segmenten. I standardströmningsreplikering har mastern ingen kunskap om slavstatusen. Ta exemplet med en master som utför en stor transaktion, medan en standby-nod är i underhållsläge under ett par timmar (som att uppgradera systempaketen, justera nätverkssäkerhet, uppgradering av hårdvara, etc.). Vid något tillfälle tar mastern bort sin transaktionslogg (WAL-segment) när kontrollpunkten passerar. När slaven är avstängd med underhåll, har den möjligen en enorm slavfördröjning och måste komma ikapp mastern. Så småningom kommer slaven att få ett ödesdigert problem som nedan:
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
Det typiska tillvägagångssättet är att ange i din postgresql.conf ett WAL-arkivskript som kopierar WAL-filer till en eller flera långtidsarkiveringsplatser. Om du inte har några väntelägen eller andra strömmande replikeringsklienter, kan i princip servern kassera WAL-filen när arkivskriptet är klart eller svarar OK. Men du behöver fortfarande några nya WAL-filer för kraschåterställning (data från de senaste WAL-filerna spelas upp under kraschåterställning. I vårt exempel på en standby-nod som är placerad under en lång underhållsperiod uppstår problem när den kommer tillbaka online och frågar den primära för en WAL-fil som den primära inte längre har, då misslyckas replikeringen.
Detta problem åtgärdades i PostgreSQL 9.4 via "Replication Slots".
Om du inte använder replikeringsplatser är ett vanligt sätt att minska risken för misslyckad replikering att ställa in wal_keep_segments tillräckligt högt så att WAL-filer som kan behövas inte roteras eller återvinns. Nackdelen med detta tillvägagångssätt är att det är svårt att avgöra vilket värde som är bäst för din installation. Du behöver inte underhåll på en daglig basis eller så behöver du inte behålla en stor hög med WAL-filer som äter upp din disklagring. Även om detta fungerar, är det inte en idealisk lösning eftersom risken för diskutrymme på mastern kan göra att inkommande transaktioner misslyckas.
Alternativa metoder för att inte använda replikeringsplatser är att konfigurera PostgreSQL med kontinuerlig arkivering och tillhandahålla ett restore_command för att ge repliken åtkomst till arkivet. För att undvika att WAL byggs upp på den primära kan du använda en separat volym eller lagringsenhet för WAL-filerna, t.ex. SAN eller NFS. En annan sak är med synkron replikering eftersom det kräver att primär måste vänta på standby-noder för att begå transaktion. Detta betyder att det säkerställer att WAL-filer har applicerats på standbynoderna. Men ändå är det bäst att du tillhandahåller arkiveringskommandon från den primära så att när WAL är återvunnen i den primära, kan du vara säker på att du har WAL-säkerhetskopior i händelse av återställning. Även om synkron replikering i vissa situationer inte är en idealisk lösning eftersom den kommer med vissa prestandakostnader jämfört med asynkron replikering.
Typer av replikeringsplatser
Det finns två typer av replikeringsplatser. Dessa är:
Fysiska replikeringsplatser
Kan användas för standard strömmande replikering. De kommer att se till att data inte återvinns för tidigt.
Logiska replikeringsplatser
Logisk replikering gör samma sak som fysiska replikeringsplatser och används för logisk replikering. De används dock för logisk avkodning. Tanken bakom logisk avkodning är att ge användare en chans att bifoga transaktionsloggen och avkoda den med en plugin. Det gör det möjligt att extrahera ändringar som gjorts i databasen och därför i transaktionsloggen i vilket format som helst och för alla ändamål.
I den här bloggen kommer vi att använda fysiska replikeringsplatser och hur man uppnår detta med ClusterControl.
Fördelar och nackdelar med att använda replikeringsplatser
Replikeringsplatser är definitivt fördelaktiga när de väl har aktiverats. Som standard är "Replication Slots" inte aktiverade och måste ställas in manuellt. Bland fördelarna med att använda replikeringsplatser är
- Se till att mastern behåller tillräckligt med WAL-segment för att alla repliker ska kunna ta emot dem
- Förhindrar mastern från att ta bort rader som kan orsaka återställningskonflikt på replikerna
- En master kan bara återvinna transaktionsloggen när den har förbrukats av alla repliker. Fördelen här är att en slav aldrig kan hamna på efterkälken så mycket att en omsynkronisering behövs.
Replikeringsplatser kommer också med några varningar.
- En föräldralös replikeringsplats kan orsaka obegränsad disktillväxt på grund av upphopade WAL-filer från mastern
- Slavnoder som placeras under långvarigt underhåll (som dagar eller veckor) och som är bundna till en replikeringsplats kommer att ha obegränsad disktillväxt på grund av WAL-filer som staplas upp från mastern
Du kan övervaka detta genom att fråga pg_replication_slots för att fastställa vilka platser som inte används. Vi återkommer om detta lite senare.
Använda replikeringsplatser
Som nämnts tidigare finns det två typer av replikeringsplatser. För den här bloggen kommer vi att använda fysiska replikeringsplatser för strömmande replikering.
Skapa en replikeringsplats
Det är enkelt att skapa en replikering. Du måste anropa den befintliga funktionen pg_create_physical_replication_slot för att göra detta och måste köras och skapas i masternoden. Funktionen är 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
t.ex. Skapar en replikeringsplats med namnet slot1,
postgres=# SELECT pg_create_physical_replication_slot('slot1');
-[ RECORD 1 ]-----------------------+---------
pg_create_physical_replication_slot | (slot1,)
Replikeringsplatsnamnen och dess underliggande konfiguration är endast systemomfattande och inte klusteromfattande. Till exempel, om du har nodA (nuvarande master) och standbynoder nodB och nodC, och skapar luckan på en masternodA nämligen "slot1", då kommer inte data att vara tillgänglig för nodB och nodC. Därför, när failover/växling är på väg att ske, måste du återskapa de platser du har skapat.
Släpp en replikeringsplats
Oanvända replikeringsplatser måste släppas eller tas bort. Som nämnts tidigare, när det finns föräldralösa replikeringsplatser eller -platser som inte har tilldelats någon klient- eller väntelägesnod, kan det leda till gränslösa problem med diskutrymme om de lämnas osläppta. Så det är mycket viktigt att dessa måste släppas när de inte längre används. För att släppa det, anropa helt enkelt pg_drop_replication_slot. Denna funktion har följande 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
Att släppa det är enkelt:
maximus_db=# select pg_drop_replication_slot('slot2');
-[ RECORD 1 ]------------+-
pg_drop_replication_slot |
Övervaka dina PostgreSQL-replikeringsplatser
Att övervaka dina replikeringsplatser är något du inte vill missa. Samla bara informationen från view pg_replication_slots i den primära/masternoden precis som nedan:
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 |
Resultatet ovan visar att main_slot har tagits, men inte main_slot2.
En annan sak du kan göra är att övervaka hur mycket eftersläpning du har. För att uppnå detta kan du helt enkelt använda frågan baserad på exempelresultatet nedan:
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 finns inte i 9.6, ska använda 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
Systemvariabelkrav
Implementering av replikeringsplatser kräver manuell inställning. Det finns variabler som du måste tänka på som kräver ändringar och specificeras i din postgresql.conf. Se nedan:
- max_replication_slots – Om satt till 0 betyder detta att replikeringsplatser är helt inaktiverade. Om du använder PostgreSQL <10 versioner, måste denna plats specificeras annat än 0 (standard). Sedan PostgreSQL 10 är standardvärdet 10. Denna variabel anger det maximala antalet replikeringsplatser. Om du ställer in det till ett lägre värde än antalet befintliga replikeringsplatser kommer servern att förhindras från att starta.
- wal_level – måste åtminstone vara replika eller högre (replika är standard). Om du ställer in hot_standby eller arkiv mappas till replik. För en fysisk replikeringsplats räcker replika. För logiska replikeringsplatser är logisk att föredra.
- max_wal_senders – inställd på 10 som standard, 0 i version 9.6 vilket betyder att replikering är inaktiverat. Vi föreslår att du ställer in detta till minst 16, särskilt när du kör med ClusterControl.
- hot_standby – i versioner <10 måste du ställa in detta till på vilket är av som standard. Detta är viktigt för standbynoder, vilket innebär att när påslaget kan du ansluta och köra frågor under återställning eller i standbyläge.
- primary_slot_name – den här variabeln ställs in via recovery.conf på standbynoden. Detta är kortplatsen som ska användas av mottagaren eller standbynoden vid anslutning till sändaren (eller primär/master).
Du måste notera att dessa variabler oftast kräver en omstart av databastjänsten för att kunna ladda om nya värden.
Använda replikeringsplatser i en ClusterControl PostgreSQL-miljö
Låt oss nu se hur vi kan använda fysiska replikeringsplatser och implementera dem i en Postgres-installation som hanteras av ClusterControl.
Isättning av PostgreSQL-databasnoder
Låt oss börja distribuera ett 3-nods PostgreSQL-kluster med ClusterControl med PostgreSQL 9.6-version den här gången.
ClusterControl kommer att distribuera noder med följande systemvariabler definierade baserat på deras standardinställningar eller justerade värden. 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 är max_replication_slots standardvärde 10 som är aktiverat som standard men inte i 9.6 eller lägre versioner som är inaktiverat som standard. Du måste tilldela max_replication_slots högre än 0. I det här exemplet satte jag max_replication_slots till 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
och startade om tjänsten,
[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
Ställa in replikeringsplatserna för primära och standbynoder
Det finns inget alternativ i ClusterControl för att göra detta, så du måste skapa dina slots manuellt. I det här exemplet skapade jag platserna i den primära i värd 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)
Kontrollera vad vi just har skapat visar,
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 standbynoderna måste vi uppdatera recovery.conf och lägga till variabeln primary_slot_name och ändra application_name så att det är lättare att identifiera noden. Så här ser det ut i värd 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 samma sak också i värd 192.168.30.120 men ändrade applikationsnamnet och ställde in primär_slot_name ='plats2'.
Kontrollerar replikeringsplatsens hälsa:
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)
Vad behöver du mer?
Eftersom ClusterControl inte stöder replikeringsplatser för närvarande finns det saker som du måste ta hänsyn till. Vad är dessa? Låt oss gå in på detaljer.
Failover/Switchover Process
När en automatisk failover eller övergång via ClusterControl har försökts, kommer platser inte att behållas från de primära och på standbynoderna. Du måste återskapa detta manuellt, kontrollera variablerna om de är korrekt inställda och ändra recovery.conf därefter.
Återbygga en slav från en mästare
När man bygger om en slav, kommer recovery.conf inte att behållas. Detta innebär att dina recovery.conf-inställningar som har det primära_slot_name kommer att raderas. Du måste ange detta manuellt igen och kontrollera vyn pg_replication_slots för att avgöra om platser används korrekt eller lämnas föräldralösa.
Om du vill bygga om slav-/väntelägesnoden från en master kan du behöva överväga att ange variabeln PGAPPNAME env precis som kommandot nedan:
$ 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
Att specificera -R-parametern är mycket viktigt så det kommer att återskapa recovery.conf, medan -S ska specificera vilket platsnamn som ska användas när standbynoden återskapas.
Slutsats
Att implementera replikeringsplatserna i PostgreSQL är enkelt men det finns vissa varningar som du måste komma ihåg. När du distribuerar med ClusterControl måste du uppdatera vissa inställningar under failover eller slav-ombyggnader.