Postgres wordt geleverd met fysieke en logische replicatiefuncties. Lees verder om meer te weten te komen over verschillende aspecten van fysieke replicatie.
Fysieke replicatie
Fysieke replicatiemethoden worden gebruikt om een volledige kopie van de volledige gegevens van een enkele cluster te behouden (in Postgres, een cluster is een set databases die wordt beheerd door een enkel Postgres-hoofdserverproces, een postmaster genoemd ), meestal op een andere machine. De bronmachine wordt de primaire . genoemd in Postgres-jargon, en de bestemming heet de standby .
Warm, warm en "koud" stand-by
Een standby-server die zo up-to-date mogelijk wordt gehouden met de primaire inreal-time en waarmee clients alleen-lezen transacties kunnen uitvoeren, wordt ahot genoemd. standby, of beter gezegd een lees replica . Hot standbys werden toegevoegd aan Postgres in versie 9, voorheen waren er alleen warme stand-by. Een warme stand-by is vergelijkbaar met een warme stand-by, behalve dat klanten er geen verbinding mee kunnen maken.
(Terzijde:Hot standbys kunnen geen query's uitvoeren die tijdelijke tabellen maken. Dit is een beperking van Postgres.)
Een "koude" stand-by (geen officiële term) is meestal een stand-by-server die pas start na een failover. Aangezien de koude stand-by niet actief is, is het mogelijk dat deze bij het opstarten eerst lopende wijzigingen moet toepassen voordat deze clientverbindingen kan accepteren.
WAL-bestanden
In de normale gang van zaken genereert een PostgreSQL-server een geordende reeks WAL-records (write ahead log). Dit zijn in feite een logboek van wijzigingen, vergelijkbaar met de AOF van Redis of de binlog van MySQL. In de kern is fysieke replicatie het transport van deze records naar een andere machine, en het verkrijgen van de andere postmaster die daar draait om deze records te accepteren en toe te passen in zijn lokale database.
WAL-records worden opgedeeld in bestanden van gelijke grootte (meestal 16 MB), genaamd WAL-segmenten of gewoon WAL-bestanden . Deze bestanden worden aangemaakt in een directory genaamd pg_wal
onder de clustergegevensdirectory (pg_wal
heette pg_xlog
in Postgres-versies vóór 10). Oude WAL-bestanden worden verwijderd wanneer ze niet langer nodig zijn (en ook op basis van een aantal configuratieparameters).
Herstelmodus
De postmaster kan worden opgestart in een modus genaamd herstelmodus , door een geldig configuratiebestand met de naam recovery.conf . te plaatsen in de clustergegevensdirectory. In herstelmodus zal Postgres alleen WAL-bestanden importeren en toepassen die zijn gegenereerd door een primaire server, en op zichzelf geen WAL-bestanden genereren. Warme en hotstandby-servers draaien in herstelmodus.
Bij het opstarten in de herstelmodus zal Postgres eerst proberen alle WAL-bestanden te importeren die beschikbaar zijn in een archief (hieronder meer). Wanneer het archief geen WAL-bestanden meer te bieden heeft, probeert het alle bestanden te importeren die rond init's pg_wal
liggen map. Als die ook klaar zijn, als een primaire verbinding is geconfigureerd en stand-by_mode is ingesteld op on
in recovery.conf zal Postgres verbinding maken met de primaire en nieuwe WAL-records ophalen en toepassen zodra ze bij de primaire worden gemaakt.
Log verzending
Stel je voor dat je een trigger hebt die wordt aangeroepen op de primaire server wanneer een nieuw WAL-bestand wordt gemaakt. Deze trigger kan dan het nieuwe WAL-bestand naar een andere machine kopiëren met bijvoorbeeld rsync
, en plaats het in de pg_wal
directory van een postmasterrunning in herstelmodus. Kun je zo een stand-by maken?
Het antwoord is ja, en dit was inderdaad de standaardpraktijk voordat streamingreplicatie werd toegevoegd in Postgres v9. Deze praktijk heet log verzending .
De trigger is een shellscript, dat kan worden geconfigureerd met archive_command. De naam en het pad van het WAL-bestand kunnen aan het script worden doorgegeven.
WAL-archivering
Laten we zeggen dat we, in plaats van te rsynchroniseren over het WAL-bestand, het kopiëren naar een S3-bucket of een NFS-gemounte map die ook toegankelijk is vanaf de standby-machine. Deze gedeelde locatie zal nu alle WAL-bestanden bevatten die door de primaire computer zijn gegenereerd. wordt een archief , en het proces van het opslaan van WAL-bestanden in het archief heet continue archivering of gewoon WAL-archivering .
Het omgekeerde van deze bewerking – het ophalen van WAL-bestanden uit het archief in Postgres in arecovery-modus – kan worden geconfigureerd met behulp vanrestore_command.Vergelijkbaar met archive_command
, dit is ook het pad naar een shellscript. De postmaster die in herstelmodus draait, weet welk WAL-bestand hij wil. De naam van het bestand kan aan het script worden doorgegeven.
Als voorbeeld zijn hier de archiverings- en herstelopdrachten voor het opslaan en ophalen van WAL-bestanden van en naar een S3-bucket:
archive_command = 's3cmd put %p s3://BUCKET/path/%f' # in postgresql.conf
restore_command = 's3cmd get s3://BUCKET/path/%f %p' # in recovery.conf
Bij opstarten in herstelmodus, als restore_command
is geconfigureerd, zal Postgres eerst proberen WAL-bestanden uit het archief op te halen.
pg_standby
In de herstelmodus weet en kan Postgres niet van tevoren hoeveel WAL-bestanden er tot nu toe zijn gegenereerd. Als restore_command is geconfigureerd, roept Postgres het herhaaldelijk aan met progressieve WAL-bestandsnamen (de namen staan in een voorspelbare volgorde) totdat het commando een fout retourneert.
De restore-opdracht kon bijvoorbeeld voldoen aan de verzoeken om WAL-bestanden000000010000000000000001
via 00000001000000000000001A
maar mislukt voor00000001000000000000001B
omdat het niet werd gevonden op de archieflocatie. Bij afwezigheid van WAL-bestanden van andere bronnen, gaat Postgres ervan uit dat het WAL-bestand 00000001000000000000001B
moet nog worden gegenereerd door de primaire en zal het herstel voltooien na het toepassen van 00000001000000000000001A
.
Bedenk wat er gebeurt als de restore-opdracht zou wachten op het bestand00000001000000000000001B
beschikbaar zijn, in plaats van af te sluiten met een fout omdat het niet is gevonden. Postgres blijft wachten op het herstelcommando en zal daarom in de herstelmodus blijven.
Dit is een geldige configuratie en een geldige manier om een warme stand-by in te stellen.
Postgres wordt geleverd met een opdracht met de naam pg_standby, die kan worden gebruikt om op deze manier een warme stand-by in te stellen, zolang het archief maar een map is.pg_standby
zal wachten tot een bestand beschikbaar is, als het niet kan worden gevonden.
Archief- en herstelopdrachten met pg_standby zien er als volgt uit:
archive_command = 'cp %p /some/path/%f' # in postgresql.conf
restore_command = 'pg_standby /some/path %f %p' # in recovery.conf
Streaming-replicatie
Na verwerking van gearchiveerde WAL-bestanden en bestanden in de pg_wal
directory, kan Postgres via het netwerk verbinding maken met een primaire server en herhaaldelijk nieuwe WAL-bestanden ophalen terwijl ze worden gemaakt. Deze functie, toegevoegd in Postgres 9, heet streaming-replicatie .
De primaire server waarmee verbinding moet worden gemaakt, kan worden opgegeven in het bestand recovery.conf:
# recovery.conf
standby_mode = on
primary_conninfo = 'host=10.0.1.10 user=repl password=p@ssw0rd'
Hot stand-by
In de herstelmodus accepteert Postgres standaard geen clientverbindingen en weigert ze de foutmeldingen "databasesysteem bevindt zich in herstelmodus". Door de regel toe te voegen hot_standby = on
in recovery.conf kunt u Postgresaccept-clientverbindingen maken en deze toestaan om alleen-lezen transacties uit te voeren:
# recovery.conf
hot_standby = on
Er is meestal geen reden om hot_standby uit te schakelen.
De PostgreSQL-documenten hebben meer informatie over het instellen en uitvoeren van een standby-modus in de "hot standby"-modus.
Replicatieslots
Replicatieslots zijn geïntroduceerd in Postgres 9.4. Ze zijn een mechanisme om nauwkeurig en duurzaam bij te houden hoe ver een standby achterloopt op de primaire. Hierdoor kan de primaire ervoor zorgen dat WAL-bestanden die nog nodig zijn om de stand-by in te halen, niet worden verwijderd.
Vóór replicatieslots was het niet mogelijk voor de primaire om dit te bepalen, en je zou in situaties terechtkomen waarin een stand-by bleef gestrand omdat een WAL-bestand dat nodig was door de primaire was verwijderd. Natuurlijk kunnen WAL-archieven dit probleem oplossen. Zonder WAL-archief was de enige optie echter om de stand-by opnieuw op te bouwen vanaf een nieuwe back-up.
U kunt hier meer lezen over replicatieslots.
Stappen om een hot-standby in te stellen
Laten we eens kijken naar de stappen die nodig zijn om een hot standby in te stellen voor een bestaande primaire.
Ten eerste hebben we een gebruiker nodig om de stand-by te verbinden als:
$ psql -p 6000
psql (11.2 (Debian 11.2-1.pgdg90+1))
Type "help" for help.
postgres=# CREATE USER repluser REPLICATION PASSWORD 'p@ssw0rd';
CREATE USER
En de bijbehorende wijzigingen in pg_hba.conf
:
# TYPE DATABASE USER ADDRESS METHOD
host replication repluser standby-ip/32 md5
# (replace standby-ip)
U kunt natuurlijk elk standaard authenticatiemechanisme van PostgreSQL gebruiken. De gebruiker moet replicatie- en inlogrechten hebben en heeft geen toegang tot een specifieke database nodig.
Zorg ervoor dat u de primaire server opnieuw laadt om de wijzigingen in pg_hba.conf door te voeren.
De stand-by moet starten vanaf een back-up van de primaire. U kunt en moet dit doen met pg_basebackup
met een nieuw replicatieslot:
pg_basebackup -h primary-ip -p 6000 -U repluser -C -S slot_standby1 -R -D standby
Dit maakt verbinding met de primaire op primary-ip:6000
met de gebruiker die we zojuist hebben aangemaakt en maakt er een back-up van in de directory standby
. Een nieuw replicatieslotslot_standby1
is gemaakt.
We gebruiken dit slot als ons standby-replicatieslot, zodat er continuïteit is van de back-up.
We hadden pg_basebackup
. gevraagd om een recovery.conf
. te maken voor ons hierboven (“-R” optie). Laten we daar eens naar kijken:
$ cat standby/recovery.conf
standby_mode = 'on'
primary_conninfo = 'user=repluser password=''p@ssw0rd'' host=primary-ip port=6000 sslmode=prefer sslcompression=0 krbsrvname=postgres target_session_attrs=any'
primary_slot_name = 'slot_standby1'
Dat is eigenlijk best goed, en we hoeven het niet verder aan te passen. Laten we nu gewoon de stand-by ter sprake brengen:
o$ pg_ctl -D standby -l log_standby -o --port=6001 start
waiting for server to start.... done
server started
postgres@stg1:/tmp/demo$ cat log_standby
2019-06-19 09:17:50.032 UTC [21733] LOG: listening on IPv4 address "127.0.0.1", port 6001
2019-06-19 09:17:50.034 UTC [21733] LOG: listening on Unix socket "/var/run/postgresql/.s.PGSQL.6001"
2019-06-19 09:17:50.067 UTC [21734] LOG: database system was interrupted; last known up at 2019-06-19 09:12:05 UTC
2019-06-19 09:17:50.111 UTC [21734] LOG: entering standby mode
2019-06-19 09:17:50.119 UTC [21734] LOG: redo starts at 0/2000028
2019-06-19 09:17:50.120 UTC [21734] LOG: consistent recovery state reached at 0/20000F8
2019-06-19 09:17:50.120 UTC [21733] LOG: database system is ready to accept read only connections
2019-06-19 09:17:50.138 UTC [21739] LOG: started streaming WAL from primary at 0/3000000 on timeline 1
En dat is het! Het logbestand geeft aan dat streamingreplicatie actief is. U zou nu verbinding moeten kunnen maken met de stand-by op poort 6001, alleen-lezen-query's uitvoeren en zien dat wijzigingen min of meer in realtime worden gerepliceerd van de primaire.
Volgende stappen
De PostgreSQLdocs zijn een geweldige plek om verder te graven in alle replicatiegerelateerde functies van Postgres. U wilt zich verdiepen in onderwerpen als vertraagde replicatie, trapsgewijze replicatie, synchrone standbys en meer.
Hoewel Postgres wordt geleverd met een indrukwekkende reeks functies, zijn er nog steeds gevallen die niet worden ondersteund. Deze wikipagina van Postgres bevat een lijst met tools van derden die aanvullende replicatiegerelateerde functionaliteit bieden.